OSDN Git Service

08f2f27bef90e71bbad7c53c3998f9947f20a11b
[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 \r
6 #define MAX_DIRBUFFER 1000\r
7 CGit g_Git;\r
8 CGit::CGit(void)\r
9 {\r
10         GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER));\r
11 }\r
12 \r
13 CGit::~CGit(void)\r
14 {\r
15 }\r
16 \r
17 char buffer[4096];\r
18 int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut)\r
19 {\r
20         SECURITY_ATTRIBUTES sa;\r
21         HANDLE hRead, hWrite;\r
22 \r
23         sa.nLength = sizeof(SECURITY_ATTRIBUTES);\r
24         sa.lpSecurityDescriptor=NULL;\r
25         sa.bInheritHandle=TRUE;\r
26         if(!CreatePipe(&hRead,&hWrite,&sa,0))\r
27         {\r
28                 return GIT_ERROR_OPEN_PIP;\r
29         }\r
30         \r
31         STARTUPINFO si;\r
32         PROCESS_INFORMATION pi;\r
33         si.cb=sizeof(STARTUPINFO);\r
34         GetStartupInfo(&si);\r
35 \r
36         si.hStdError=hWrite;\r
37         si.hStdOutput=hWrite;\r
38         si.wShowWindow=SW_HIDE;\r
39         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
40 \r
41         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
42         {\r
43                 LPVOID lpMsgBuf;\r
44                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
45                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
46                         (LPTSTR)&lpMsgBuf,\r
47                         0,NULL);\r
48                 return GIT_ERROR_CREATE_PROCESS;\r
49         }\r
50         \r
51         CloseHandle(hWrite);\r
52         if(piOut)\r
53                 *piOut=pi;\r
54         if(hReadOut)\r
55                 *hReadOut=hRead;\r
56         \r
57         return 0;\r
58 \r
59 }\r
60 int CGit::Run(CString cmd, CString* output)\r
61 {\r
62         PROCESS_INFORMATION pi;\r
63         HANDLE hRead;\r
64         if(RunAsync(cmd,&pi,&hRead))\r
65                 return GIT_ERROR_CREATE_PROCESS;\r
66 \r
67         DWORD readnumber;\r
68         while(ReadFile(hRead,buffer,4090,&readnumber,NULL))\r
69         {\r
70                 buffer[readnumber]=0;\r
71                 USES_CONVERSION;\r
72                 output->Append(A2W(buffer));\r
73         }\r
74 \r
75         \r
76         CloseHandle(pi.hThread);\r
77 \r
78         WaitForSingleObject(pi.hProcess, INFINITE);\r
79         DWORD exitcode =0;\r
80 \r
81         if(!GetExitCodeProcess(pi.hProcess,&exitcode))\r
82         {\r
83                 return GIT_ERROR_GET_EXIT_CODE;\r
84         }\r
85 \r
86         CloseHandle(pi.hProcess);\r
87 \r
88         CloseHandle(hRead);\r
89         return exitcode;\r
90 }\r
91 \r
92 CString CGit::GetUserName(void)\r
93 {\r
94         CString UserName;\r
95         Run(_T("git.cmd config user.name"),&UserName);\r
96         return UserName;\r
97 }\r
98 CString CGit::GetUserEmail(void)\r
99 {\r
100         CString UserName;\r
101         Run(_T("git.cmd config user.email"),&UserName);\r
102         return UserName;\r
103 }\r
104 \r
105 CString CGit::GetCurrentBranch(void)\r
106 {\r
107         CString branch;\r
108         Run(_T("git.cmd branch"),&branch);\r
109         if(branch.GetLength()>0)\r
110         {\r
111                 branch.Replace(_T('*'),_T(' '));\r
112                 branch.TrimLeft();\r
113                 return branch;\r
114         }\r
115         return CString("");\r
116 }\r
117 \r
118 int CGit::GetLog(CString& logOut)\r
119 {\r
120 \r
121         CString cmd;\r
122         CString log;\r
123         cmd=("git.cmd log -C --numstat --raw --pretty=format:\"");\r
124         log.Format(_T("#<%c>%%n"),LOG_REV_ITEM_BEGIN);\r
125         cmd += log;\r
126         log.Format(_T("#<%c>%%an%%n"),LOG_REV_AUTHOR_NAME);\r
127         cmd += log;\r
128         log.Format(_T("#<%c>%%ae%%n"),LOG_REV_AUTHOR_EMAIL);\r
129         cmd += log;\r
130         log.Format(_T("#<%c>%%ai%%n"),LOG_REV_AUTHOR_DATE);\r
131         cmd += log;\r
132         log.Format(_T("#<%c>%%cn%%n"),LOG_REV_COMMIT_NAME);\r
133         cmd += log;\r
134         log.Format(_T("#<%c>%%ce%%n"),LOG_REV_COMMIT_EMAIL);\r
135         cmd += log;\r
136         log.Format(_T("#<%c>%%ci%%n"),LOG_REV_COMMIT_DATE);\r
137         cmd += log;\r
138         log.Format(_T("#<%c>%%s%%n"),LOG_REV_COMMIT_SUBJECT);\r
139         cmd += log;\r
140         log.Format(_T("#<%c>%%b%%n"),LOG_REV_COMMIT_BODY);\r
141         cmd += log;\r
142         log.Format(_T("#<%c>%%H%%n"),LOG_REV_COMMIT_HASH);\r
143         cmd += log;\r
144         log.Format(_T("#<%c>%%P%%n"),LOG_REV_COMMIT_PARENT);\r
145         cmd += log;\r
146         log.Format(_T("#<%c>%%n"),LOG_REV_COMMIT_FILE);\r
147         cmd += log;\r
148         cmd += CString(_T("\" HEAD~40..HEAD"));\r
149         Run(cmd,&logOut);\r
150         return 0;\r
151 }\r
152 \r
153 #define BUFSIZE 512\r
154 void GetTempPath(CString &path)\r
155 {\r
156         TCHAR lpPathBuffer[BUFSIZE];\r
157         DWORD dwRetVal;\r
158         DWORD dwBufSize=BUFSIZE;\r
159         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
160                            lpPathBuffer); // buffer for path \r
161     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
162     {\r
163         path=_T("");\r
164     }\r
165         path.Format(_T("%s"),lpPathBuffer);\r
166 }\r
167 CString GetTempFile()\r
168 {\r
169         TCHAR lpPathBuffer[BUFSIZE];\r
170         DWORD dwRetVal;\r
171     DWORD dwBufSize=BUFSIZE;\r
172         TCHAR szTempName[BUFSIZE];  \r
173         UINT uRetVal;\r
174 \r
175         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
176                            lpPathBuffer); // buffer for path \r
177     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
178     {\r
179         return _T("");\r
180     }\r
181          // Create a temporary file. \r
182     uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files\r
183                               TEXT("Patch"),  // temp file name prefix \r
184                               0,            // create unique name \r
185                               szTempName);  // buffer for name \r
186 \r
187 \r
188     if (uRetVal == 0)\r
189     {\r
190         return _T("");\r
191     }\r
192 \r
193         return CString(szTempName);\r
194 \r
195 }\r
196 \r
197 int CGit::RunLogFile(CString cmd,CString &filename)\r
198 {\r
199         HANDLE hRead, hWrite;\r
200 \r
201         STARTUPINFO si;\r
202         PROCESS_INFORMATION pi;\r
203         si.cb=sizeof(STARTUPINFO);\r
204         GetStartupInfo(&si);\r
205 \r
206         SECURITY_ATTRIBUTES   psa={sizeof(psa),NULL,TRUE};;   \r
207         psa.bInheritHandle=TRUE;   \r
208     \r
209         HANDLE   houtfile=CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
210                         &psa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);   \r
211 \r
212 \r
213         si.wShowWindow=SW_HIDE;\r
214         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
215         si.hStdOutput   =   houtfile; \r
216         \r
217         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
218         {\r
219                 LPVOID lpMsgBuf;\r
220                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
221                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
222                         (LPTSTR)&lpMsgBuf,\r
223                         0,NULL);\r
224                 return GIT_ERROR_CREATE_PROCESS;\r
225         }\r
226         \r
227         WaitForSingleObject(pi.hProcess,INFINITE);   \r
228         \r
229         CloseHandle(pi.hThread);\r
230         CloseHandle(pi.hProcess);\r
231         CloseHandle(houtfile);\r
232         return GIT_SUCCESS;\r
233         return 0;\r
234 }\r
235 \r
236 git_revnum_t CGit::GetHash(CString &friendname)\r
237 {\r
238         CString cmd;\r
239         CString out;\r
240         cmd.Format(_T("git.cmd rev-parse %s" ),friendname);\r
241         Run(cmd,&out);\r
242         int pos=out.ReverseFind(_T('\n'));\r
243         if(pos>0)\r
244                 return out.Left(pos);\r
245         return out;\r
246 }\r
247 \r
248 int CGit::GetTagList(CStringList &list)\r
249 {\r
250         int ret;\r
251         CString cmd,output;\r
252         cmd=_T("git.exe tag -l");\r
253         int i=0;\r
254         ret=g_Git.Run(cmd,&output);\r
255         if(!ret)\r
256         {               \r
257                 int pos=0;\r
258                 CString one;\r
259                 while( pos>=0 )\r
260                 {\r
261                         i++;\r
262                         one=output.Tokenize(_T("\n"),pos);\r
263                         list.AddTail(one);\r
264                 }\r
265         }\r
266         return ret;\r
267 }\r
268 \r
269 int CGit::GetBranchList(CStringList &list,int *current,BRANCH_TYPE type)\r
270 {\r
271         int ret;\r
272         CString cmd,output;\r
273         cmd=_T("git.exe branch");\r
274 \r
275         if(type==(BRANCH_LOCAL|BRANCH_REMOTE))\r
276                 cmd+=_T(" -a");\r
277         else if(type==BRANCH_REMOTE)\r
278                 cmd+=_T(" -r");\r
279 \r
280         int i=0;\r
281         ret=g_Git.Run(cmd,&output);\r
282         if(!ret)\r
283         {               \r
284                 int pos=0;\r
285                 CString one;\r
286                 while( pos>=0 )\r
287                 {\r
288                         i++;\r
289                         one=output.Tokenize(_T("\n"),pos);\r
290                         list.AddTail(one.Right(one.GetLength()-2));\r
291                         if(one[0] == _T('*'))\r
292                                 if(current)\r
293                                         *current=i;\r
294                 }\r
295         }\r
296         return ret;\r
297 }\r
298 \r
299 int CGit::GetRemoteList(CStringList &list)\r
300 {\r
301         int ret;\r
302         CString cmd,output;\r
303         cmd=_T("git.exe config  --get-regexp remote.*.url");\r
304         ret=g_Git.Run(cmd,&output);\r
305         if(!ret)\r
306         {\r
307                 int pos=0;\r
308                 CString one;\r
309                 while( pos>=0 )\r
310                 {\r
311                         one=output.Tokenize(_T("\n"),pos);\r
312                         int start=one.Find(_T("."),0);\r
313                         if(start>0)\r
314                         {\r
315                                 CString url;\r
316                                 url=one.Right(one.GetLength()-start-1);\r
317                                 one=url;\r
318                                 one=one.Left(one.Find(_T("."),0));\r
319                                 list.AddTail(one);\r
320                         }\r
321                 }\r
322         }\r
323         return ret;\r
324 }\r
325 \r
326 int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map)\r
327 {\r
328         int ret;\r
329         CString cmd,output;\r
330         cmd=_T("git show-ref");\r
331         ret=g_Git.Run(cmd,&output);\r
332         if(!ret)\r
333         {\r
334                 int pos=0;\r
335                 CString one;\r
336                 while( pos>=0 )\r
337                 {\r
338                         one=output.Tokenize(_T("\n"),pos);\r
339                         int start=one.Find(_T(" "),0);\r
340                         if(start>0)\r
341                         {\r
342                                 CString name;\r
343                                 name=one.Right(one.GetLength()-start-1);\r
344 \r
345                                 CString hash;\r
346                                 hash=one.Left(start);\r
347 \r
348                                 map[hash].push_back(name);\r
349                         }\r
350                 }\r
351         }\r
352         return ret;\r
353 }