OSDN Git Service

Add git_close_diff function when call it when program exist.
[tortoisegit/TortoiseGitJp.git] / ext / gitdll / gitdll.c
1 // gitdll.cpp : Defines the exported functions for the DLL application.\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "git-compat-util.h"\r
6 #include "msvc.h"\r
7 #include "gitdll.h"\r
8 #include "cache.h"\r
9 #include "commit.h"\r
10 #include "diff.h"\r
11 #include "revision.h"\r
12 #include "diffcore.h"\r
13 const char git_version_string[] = GIT_VERSION;\r
14 \r
15 \r
16 #if 0\r
17 \r
18 // This is an example of an exported variable\r
19 GITDLL_API int ngitdll=0;\r
20 \r
21 // This is an example of an exported function.\r
22 GITDLL_API int fngitdll(void)\r
23 {\r
24         return 42;\r
25 }\r
26 \r
27 // This is the constructor of a class that has been exported.\r
28 // see gitdll.h for the class definition\r
29 Cgitdll::Cgitdll()\r
30 {\r
31         return;\r
32 }\r
33 #endif\r
34 \r
35 #define MAX_ERROR_STR_SIZE 512\r
36 char g_last_error[MAX_ERROR_STR_SIZE]={0};\r
37 void * g_prefix;\r
38 \r
39 char * get_git_last_error()\r
40 {\r
41         return g_last_error;\r
42 }\r
43 \r
44 static void die_dll(const char *err, va_list params)\r
45 {\r
46         memset(g_last_error,0,MAX_ERROR_STR_SIZE);\r
47         vsnprintf(g_last_error, MAX_ERROR_STR_SIZE-1, err, params);     \r
48 }\r
49 \r
50 void dll_entry()\r
51 {\r
52         set_die_routine(die_dll);\r
53 }\r
54 \r
55 int git_get_sha1(const char *name, GIT_HASH sha1)\r
56 {\r
57         return get_sha1(name,sha1);\r
58 }\r
59 \r
60 static int convert_slash(char * path)\r
61 {\r
62         while(*path)\r
63         {\r
64                 if(*path == '\\' )\r
65                         *path = '/';\r
66                 path++;\r
67         }\r
68 }\r
69 \r
70 int git_init()\r
71 {\r
72         char *home;\r
73         char path[MAX_PATH+1];\r
74         char *prefix;\r
75         size_t homesize,size,httpsize;\r
76 \r
77         // set HOME if not set already\r
78         getenv_s(&homesize, NULL, 0, "HOME");\r
79         if (!homesize)\r
80         {\r
81                 _dupenv_s(&home,&size,"USERPROFILE"); \r
82                 _putenv_s("HOME",home);\r
83                 free(home);\r
84         }\r
85         GetModuleFileName(NULL, path, MAX_PATH);\r
86         convert_slash(path);\r
87 \r
88         git_extract_argv0_path(path);\r
89         g_prefix = prefix = setup_git_directory();\r
90         return git_config(git_default_config, NULL);\r
91 }\r
92 \r
93 static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR *author, char *pbuff)\r
94 {\r
95         char *end;\r
96 \r
97         author->Name=pbuff;\r
98         end=strchr(pbuff,'<');\r
99         if( end == 0)\r
100         {\r
101                 return -1;\r
102         }\r
103         author->NameSize = end - pbuff - 1;\r
104 \r
105         pbuff = end +1;\r
106         end = strchr(pbuff, '>');\r
107         if( end == 0)\r
108                 return -1;\r
109 \r
110         author->Email = pbuff ;\r
111         author->EmailSize = end - pbuff;\r
112 \r
113         pbuff = end + 2;\r
114 \r
115         author->Date = atol(pbuff);\r
116         end =  strchr(pbuff, ' ');\r
117         if( end == 0 )\r
118                 return -1;\r
119 \r
120         pbuff=end;\r
121         author->TimeZone = atol(pbuff);\r
122 \r
123         return 0;\r
124 }\r
125 \r
126 int git_parse_commit(GIT_COMMIT *commit)\r
127 {\r
128         int ret = 0;\r
129         char *pbuf;\r
130         char *end;\r
131         struct commit *p;\r
132 \r
133         p= (struct commit *)commit->m_pGitCommit;\r
134 \r
135         memcpy(commit->m_hash,p->object.sha1,GIT_HASH_SIZE);\r
136 \r
137         if(p->buffer == NULL)\r
138                 return -1;\r
139 \r
140         pbuf = p->buffer;\r
141         while(pbuf)\r
142         {\r
143                 if( strncmp(pbuf,"author",6) == 0)\r
144                 {\r
145                         ret = git_parse_commit_author(&commit->m_Author,pbuf + 7);\r
146                         if(ret)\r
147                                 return ret;\r
148                 }\r
149                 if( strncmp(pbuf, "committer",9) == 0)\r
150                 {\r
151                         ret =  git_parse_commit_author(&commit->m_Committer,pbuf + 10);\r
152                         if(ret)\r
153                                 return ret;\r
154 \r
155                         pbuf = strchr(pbuf,'\n');\r
156                         if(pbuf == NULL)\r
157                                 return -1;\r
158 \r
159                         while((*pbuf) && (*pbuf == '\n'))\r
160                                 pbuf ++;\r
161 \r
162                         commit->m_Subject=pbuf;\r
163                         end = strchr(pbuf,'\n');\r
164                         if( end == 0)\r
165                                 commit->m_SubjectSize = strlen(pbuf);\r
166                         else\r
167                         {\r
168                                 commit->m_SubjectSize = end - pbuf;\r
169                                 pbuf = end +1;\r
170                                 commit->m_Body = pbuf;\r
171                                 commit->m_BodySize = strlen(pbuf);\r
172                                 return 0;\r
173                         }\r
174 \r
175                 }\r
176 \r
177                 pbuf = strchr(pbuf,'\n');\r
178                 if(pbuf)\r
179                         pbuf ++;\r
180         }\r
181 \r
182 }\r
183 \r
184 int git_get_commit_from_hash(GIT_COMMIT *commit, GIT_HASH hash)\r
185 {\r
186         int ret = 0;\r
187         \r
188         struct commit *p;\r
189         commit->m_pGitCommit = p = lookup_commit(hash);\r
190 \r
191         if(commit == NULL)\r
192                 return -1;\r
193         \r
194         if(p == NULL)\r
195                 return -1;\r
196         \r
197         ret = parse_commit(p);\r
198         if( ret )\r
199                 return ret;\r
200 \r
201         return git_parse_commit(commit);\r
202 }\r
203 \r
204 int git_get_commit_first_parent(GIT_COMMIT *commit,GIT_COMMIT_LIST *list)\r
205 {\r
206         struct commit *p = commit->m_pGitCommit;\r
207 \r
208         if(list == NULL)\r
209                 return -1;\r
210         \r
211         *list = (GIT_COMMIT_LIST*)p->parents;\r
212         return 0;\r
213 }\r
214 int git_get_commit_next_parent(GIT_COMMIT_LIST *list, GIT_HASH hash)\r
215 {\r
216         struct commit_list *l = *(struct commit_list **)list;\r
217         if(list == NULL || l==NULL)\r
218                 return -1;\r
219 \r
220         if(hash)\r
221                 memcpy(hash, l->item->object.sha1, GIT_HASH_SIZE);\r
222 \r
223         *list = (GIT_COMMIT_LIST *)l->next;\r
224         return 0;\r
225 \r
226 }\r
227 \r
228 \r
229 int git_free_commit(GIT_COMMIT *commit)\r
230 {\r
231         struct commit *p = commit->m_pGitCommit;\r
232 \r
233         if( p->parents)\r
234                 free_commit_list(p->parents);   \r
235 \r
236         if( p->buffer )\r
237         {\r
238                 free(p->buffer);\r
239                 p->buffer=NULL;\r
240                 p->object.parsed=0;\r
241                 p->parents=0;\r
242                 p->tree=0;\r
243         }\r
244         memset(commit,0,sizeof(GIT_COMMIT));\r
245         return 0;\r
246 }\r
247 \r
248 char **strtoargv(char *arg, int *size)\r
249 {\r
250         int count=0;\r
251         char *p=arg;\r
252         char **argv;\r
253         int i=0;\r
254         while(*p)\r
255         {\r
256                 if(*p == ' ')\r
257                         count ++;\r
258                 p++;\r
259         }\r
260         \r
261         argv=malloc(strlen(arg)+1 + (count +2)*sizeof(void*));\r
262         p=(char*)(argv+count+2);\r
263 \r
264         while(*arg)\r
265         {\r
266                 if(*arg == '"')\r
267                 {\r
268                         argv[i] = p;\r
269                         arg++;\r
270                         *p=*arg;\r
271                         while(*arg && *arg!= '"')\r
272                                 *p++=*arg++;\r
273                         *p++=0;\r
274                         arg++;\r
275                         i++;\r
276                         if(*arg == 0)\r
277                                 break;\r
278                 }\r
279                 if(*arg != ' ')\r
280                 {\r
281                         argv[i]=p;\r
282                         while(*arg && *arg !=' ')\r
283                                 *p++ = *arg++;\r
284                         i++;\r
285                         *p++=0;\r
286                 }\r
287                 arg++;\r
288         }\r
289         argv[i]=NULL;\r
290         *size = i;\r
291         return argv;\r
292 }\r
293 int git_open_log(GIT_LOG * handle, char * arg)\r
294 {\r
295         struct rev_info *p_Rev;\r
296         int size;\r
297         char ** argv=0;\r
298         int argc=0;\r
299         \r
300         if(arg != NULL)\r
301                 argv = strtoargv(arg,&argc);\r
302 \r
303         p_Rev = malloc(sizeof(struct rev_info));\r
304         memset(p_Rev,0,sizeof(struct rev_info));\r
305 \r
306         if(p_Rev == NULL)\r
307                 return -1;\r
308 \r
309         init_revisions(p_Rev, g_prefix);\r
310         p_Rev->diff = 1;\r
311         p_Rev->simplify_history = 0;\r
312         \r
313         cmd_log_init(argc, argv, g_prefix,p_Rev);\r
314 \r
315         p_Rev->pPrivate = argv;\r
316         *handle = p_Rev;\r
317         return 0;\r
318 \r
319 }\r
320 int git_get_log_firstcommit(GIT_LOG handle)\r
321 {\r
322         return prepare_revision_walk(handle);\r
323 }\r
324 \r
325 int git_get_log_nextcommit(GIT_LOG handle, GIT_COMMIT *commit)\r
326 {\r
327         int ret =0;\r
328 \r
329         commit->m_pGitCommit = get_revision(handle);\r
330         if( commit->m_pGitCommit == NULL)\r
331                 return -2;\r
332         \r
333         ret=git_parse_commit(commit);\r
334         if(ret)\r
335                 return ret;\r
336 \r
337         return 0;\r
338 }\r
339 \r
340 int git_close_log(GIT_LOG handle)\r
341 {\r
342         if(handle)\r
343         {\r
344                 struct rev_info *p_Rev;\r
345                 p_Rev=(struct rev_info *)handle;\r
346                 if(p_Rev->pPrivate)\r
347                         free(p_Rev->pPrivate);\r
348                 free(handle);\r
349         }\r
350         \r
351         return 0;\r
352 }\r
353 \r
354 int git_open_diff(GIT_DIFF *diff, char * arg)\r
355 {\r
356         struct rev_info *p_Rev;\r
357         int size;\r
358         char ** argv=0;\r
359         int argc=0;\r
360                 \r
361         if(arg != NULL)\r
362                 argv = strtoargv(arg,&argc);\r
363 \r
364         p_Rev = malloc(sizeof(struct rev_info));\r
365         memset(p_Rev,0,sizeof(struct rev_info));\r
366 \r
367         p_Rev->pPrivate = argv;\r
368         *diff = (GIT_DIFF)p_Rev;\r
369 \r
370         init_revisions(p_Rev, g_prefix);\r
371         git_config(git_diff_basic_config, NULL); /* no "diff" UI options */\r
372         p_Rev->abbrev = 0;\r
373         p_Rev->diff = 1;\r
374         argc = setup_revisions(argc, argv, p_Rev, NULL);\r
375 \r
376         return 0;\r
377 }\r
378 int git_close_diff(GIT_DIFF handle)\r
379 {\r
380         git_diff_flush(handle);\r
381         if(handle)\r
382         {\r
383                 struct rev_info *p_Rev;\r
384                 p_Rev=(struct rev_info *)handle;\r
385                 if(p_Rev->pPrivate)\r
386                         free(p_Rev->pPrivate);\r
387                 free(handle);\r
388         }\r
389         return 0;\r
390 }\r
391 int git_diff_flush(GIT_DIFF diff)\r
392 {\r
393         struct diff_queue_struct *q = &diff_queued_diff;\r
394         struct rev_info *p_Rev;\r
395         int i;\r
396         p_Rev = (struct rev_info *)diff;\r
397         \r
398         if(q->nr == 0)\r
399                 return 0;\r
400 \r
401         for (i = 0; i < q->nr; i++)\r
402                 diff_free_filepair(q->queue[i]);\r
403 \r
404         if(q->queue)\r
405         {\r
406                 free(q->queue);\r
407                 q->queue = NULL;\r
408                 q->nr = q->alloc = 0;\r
409         }\r
410 \r
411         if (p_Rev->diffopt.close_file)\r
412                 fclose(p_Rev->diffopt.close_file);\r
413 \r
414         free_diffstat_info(&p_Rev->diffstat);\r
415 }\r
416 int git_diff(GIT_DIFF diff, GIT_HASH hash1, GIT_HASH hash2, GIT_FILE * file, int *count)\r
417 {\r
418         struct rev_info *p_Rev;\r
419         int ret;\r
420         int i;\r
421         struct diff_queue_struct *q = &diff_queued_diff;\r
422         \r
423         p_Rev = (struct rev_info *)diff;\r
424 \r
425         ret = diff_tree_sha1(hash1,hash2,"",&p_Rev->diffopt);\r
426         if( ret )\r
427                 return ret;\r
428         \r
429         diffcore_std(&p_Rev->diffopt);\r
430 \r
431         memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));\r
432         for (i = 0; i < q->nr; i++) {\r
433                 struct diff_filepair *p = q->queue[i];\r
434                 //if (check_pair_status(p))\r
435                 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);\r
436         }\r
437 \r
438         if(file)\r
439                 *file = q;\r
440         if(count)\r
441                 *count = q->nr;\r
442         return 0;\r
443 }\r
444 \r
445 int git_get_diff_file(GIT_DIFF diff,GIT_FILE file,int i, char **newname, char ** oldname,  int *status, int *IsBin, int *inc, int *dec)\r
446 {\r
447         struct diff_queue_struct *q = &diff_queued_diff;\r
448         struct rev_info *p_Rev;\r
449         p_Rev = (struct rev_info *)diff;\r
450         \r
451         q = (struct diff_queue_struct *)file;\r
452         if(file == 0)\r
453                 return -1;\r
454         if(i>=q->nr)\r
455                 return -1;\r
456 \r
457         if(newname)\r
458                 *newname = q->queue[i]->one->path;\r
459 \r
460         if(oldname)\r
461                 *oldname = q->queue[i]->two->path;\r
462 \r
463         if(status)\r
464                 *status = q->queue[i]->status;\r
465 \r
466         if(p_Rev->diffstat.files)\r
467         {\r
468                 int j;\r
469                 for(j=0;j<p_Rev->diffstat.nr;j++)\r
470                 {\r
471                         if(strcmp(*newname,p_Rev->diffstat.files[j]->name)==0)\r
472                                 break;\r
473                 }\r
474                 if( j== p_Rev->diffstat.nr)\r
475                 {\r
476                         *IsBin=1;\r
477                         *inc=0;\r
478                         *dec=0;\r
479                         return 0;\r
480                 }\r
481                 if(IsBin)\r
482                         *IsBin = p_Rev->diffstat.files[j]->is_binary;\r
483                 if(inc)\r
484                         *inc = p_Rev->diffstat.files[j]->added;\r
485                 if(dec)\r
486                         *dec = p_Rev->diffstat.files[j]->deleted;\r
487         }else\r
488         {\r
489                 *IsBin=1;\r
490                 *inc=0;\r
491                 *dec=0;\r
492         }\r
493 \r
494         return 0;\r
495 }