Fix 64bit crash problem at log dialog
[TortoiseGit.git] / ext / gitdll / gitdll.c
blob77607b177b5cce9f57457a9d1e10bb73da38f5d8
1 // gitdll.cpp : Defines the exported functions for the DLL application.
2 //
4 #include "stdafx.h"
5 #include "git-compat-util.h"
6 #include "msvc.h"
7 #include "gitdll.h"
8 #include "cache.h"
9 #include "commit.h"
10 #include "diff.h"
11 #include "revision.h"
12 #include "diffcore.h"
13 const char git_version_string[] = GIT_VERSION;
16 #if 0
18 // This is an example of an exported variable
19 GITDLL_API int ngitdll=0;
21 // This is an example of an exported function.
22 GITDLL_API int fngitdll(void)
24 return 42;
27 // This is the constructor of a class that has been exported.
28 // see gitdll.h for the class definition
29 Cgitdll::Cgitdll()
31 return;
33 #endif
35 #define MAX_ERROR_STR_SIZE 512
36 char g_last_error[MAX_ERROR_STR_SIZE]={0};
37 void * g_prefix;
39 char * get_git_last_error()
41 return g_last_error;
44 static void die_dll(const char *err, va_list params)
46 memset(g_last_error,0,MAX_ERROR_STR_SIZE);
47 vsnprintf(g_last_error, MAX_ERROR_STR_SIZE-1, err, params);
50 void dll_entry()
52 set_die_routine(die_dll);
55 int git_get_sha1(const char *name, GIT_HASH sha1)
57 return get_sha1(name,sha1);
60 static int convert_slash(char * path)
62 while(*path)
64 if(*path == '\\' )
65 *path = '/';
66 path++;
70 int git_init()
72 char *home;
73 char path[MAX_PATH+1];
74 char *prefix;
75 size_t homesize,size,httpsize;
77 _fmode = _O_BINARY;
78 _setmode(_fileno(stdin), _O_BINARY);
79 _setmode(_fileno(stdout), _O_BINARY);
80 _setmode(_fileno(stderr), _O_BINARY);
82 // set HOME if not set already
83 getenv_s(&homesize, NULL, 0, "HOME");
84 if (!homesize)
86 _dupenv_s(&home,&size,"USERPROFILE");
87 _putenv_s("HOME",home);
88 free(home);
90 GetModuleFileName(NULL, path, MAX_PATH);
91 convert_slash(path);
93 git_extract_argv0_path(path);
94 g_prefix = prefix = setup_git_directory();
95 return git_config(git_default_config, NULL);
98 static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR *author, char *pbuff)
100 char *end;
102 author->Name=pbuff;
103 end=strchr(pbuff,'<');
104 if( end == 0)
106 return -1;
108 author->NameSize = end - pbuff - 1;
110 pbuff = end +1;
111 end = strchr(pbuff, '>');
112 if( end == 0)
113 return -1;
115 author->Email = pbuff ;
116 author->EmailSize = end - pbuff;
118 pbuff = end + 2;
120 author->Date = atol(pbuff);
121 end = strchr(pbuff, ' ');
122 if( end == 0 )
123 return -1;
125 pbuff=end;
126 author->TimeZone = atol(pbuff);
128 return 0;
131 int git_parse_commit(GIT_COMMIT *commit)
133 int ret = 0;
134 char *pbuf;
135 char *end;
136 struct commit *p;
138 p= (struct commit *)commit->m_pGitCommit;
140 memcpy(commit->m_hash,p->object.sha1,GIT_HASH_SIZE);
142 commit->m_Encode = NULL;
143 commit->m_EncodeSize = 0;
145 if(p->buffer == NULL)
146 return -1;
148 pbuf = p->buffer;
149 while(pbuf)
151 if( strncmp(pbuf,"author",6) == 0)
153 ret = git_parse_commit_author(&commit->m_Author,pbuf + 7);
154 if(ret)
155 return ret;
157 if( strncmp(pbuf, "committer",9) == 0)
159 ret = git_parse_commit_author(&commit->m_Committer,pbuf + 10);
160 if(ret)
161 return ret;
163 pbuf = strchr(pbuf,'\n');
164 if(pbuf == NULL)
165 return -1;
167 while((*pbuf) && (*pbuf == '\n'))
168 pbuf ++;
170 if( strncmp(pbuf, "encoding",8) == 0 )
172 pbuf += 9;
173 commit->m_Encode=pbuf;
174 end = strchr(pbuf,'\n');
175 commit->m_EncodeSize=end -pbuf;
177 pbuf = end +1;
178 while((*pbuf) && (*pbuf == '\n'))
179 pbuf ++;
181 commit->m_Subject=pbuf;
182 end = strchr(pbuf,'\n');
183 if( end == 0)
184 commit->m_SubjectSize = strlen(pbuf);
185 else
187 commit->m_SubjectSize = end - pbuf;
188 pbuf = end +1;
189 commit->m_Body = pbuf;
190 commit->m_BodySize = strlen(pbuf);
191 return 0;
196 pbuf = strchr(pbuf,'\n');
197 if(pbuf)
198 pbuf ++;
203 int git_get_commit_from_hash(GIT_COMMIT *commit, GIT_HASH hash)
205 int ret = 0;
207 struct commit *p;
209 memset(commit,0,sizeof(GIT_COMMIT));
211 commit->m_pGitCommit = p = lookup_commit(hash);
213 if(commit == NULL)
214 return -1;
216 if(p == NULL)
217 return -1;
219 ret = parse_commit(p);
220 if( ret )
221 return ret;
223 return git_parse_commit(commit);
226 int git_get_commit_first_parent(GIT_COMMIT *commit,GIT_COMMIT_LIST *list)
228 struct commit *p = commit->m_pGitCommit;
230 if(list == NULL)
231 return -1;
233 *list = (GIT_COMMIT_LIST*)p->parents;
234 return 0;
236 int git_get_commit_next_parent(GIT_COMMIT_LIST *list, GIT_HASH hash)
238 struct commit_list *l = *(struct commit_list **)list;
239 if(list == NULL || l==NULL)
240 return -1;
242 if(hash)
243 memcpy(hash, l->item->object.sha1, GIT_HASH_SIZE);
245 *list = (GIT_COMMIT_LIST *)l->next;
246 return 0;
251 int git_free_commit(GIT_COMMIT *commit)
253 struct commit *p = commit->m_pGitCommit;
255 if( p->parents)
256 free_commit_list(p->parents);
258 if( p->buffer )
260 free(p->buffer);
261 p->buffer=NULL;
262 p->object.parsed=0;
263 p->parents=0;
264 p->tree=0;
266 memset(commit,0,sizeof(GIT_COMMIT));
267 return 0;
270 char **strtoargv(char *arg, int *size)
272 int count=0;
273 char *p=arg;
274 char **argv;
276 int i=0;
277 while(*p)
279 if(*p == '\\')
280 *p='/';
281 p++;
283 p=arg;
285 while(*p)
287 if(*p == ' ')
288 count ++;
289 p++;
292 argv=malloc(strlen(arg)+1 + (count +2)*sizeof(void*));
293 p=(char*)(argv+count+2);
295 while(*arg)
297 if(*arg == '"')
299 argv[i] = p;
300 arg++;
301 *p=*arg;
302 while(*arg && *arg!= '"')
303 *p++=*arg++;
304 *p++=0;
305 arg++;
306 i++;
307 if(*arg == 0)
308 break;
310 if(*arg != ' ')
312 argv[i]=p;
313 while(*arg && *arg !=' ')
314 *p++ = *arg++;
315 i++;
316 *p++=0;
318 arg++;
320 argv[i]=NULL;
321 *size = i;
322 return argv;
324 int git_open_log(GIT_LOG * handle, char * arg)
326 struct rev_info *p_Rev;
327 int size;
328 char ** argv=0;
329 int argc=0;
330 int i=0;
332 /* clear flags */
333 unsigned int obj_size = get_max_object_index();
334 for(i =0; i<obj_size; i++)
336 struct object *ob= get_indexed_object(i);
337 if(ob)
338 ob->flags=0;
341 if(arg != NULL)
342 argv = strtoargv(arg,&argc);
344 p_Rev = malloc(sizeof(struct rev_info));
345 memset(p_Rev,0,sizeof(struct rev_info));
347 if(p_Rev == NULL)
348 return -1;
350 init_revisions(p_Rev, g_prefix);
351 p_Rev->diff = 1;
353 cmd_log_init(argc, argv, g_prefix,p_Rev);
355 p_Rev->pPrivate = argv;
356 *handle = p_Rev;
357 return 0;
360 int git_get_log_firstcommit(GIT_LOG handle)
362 return prepare_revision_walk(handle);
365 int git_get_log_estimate_commit_count(GIT_LOG handle)
367 struct rev_info *p_Rev;
368 p_Rev=(struct rev_info *)handle;
370 return estimate_commit_count(p_Rev, p_Rev->commits);
373 int git_get_log_nextcommit(GIT_LOG handle, GIT_COMMIT *commit)
375 int ret =0;
377 commit->m_pGitCommit = get_revision(handle);
378 if( commit->m_pGitCommit == NULL)
379 return -2;
381 ret=git_parse_commit(commit);
382 if(ret)
383 return ret;
385 return 0;
388 int git_close_log(GIT_LOG handle)
390 if(handle)
392 struct rev_info *p_Rev;
393 p_Rev=(struct rev_info *)handle;
394 if(p_Rev->pPrivate)
395 free(p_Rev->pPrivate);
396 free(handle);
399 return 0;
402 int git_open_diff(GIT_DIFF *diff, char * arg)
404 struct rev_info *p_Rev;
405 int size;
406 char ** argv=0;
407 int argc=0;
409 if(arg != NULL)
410 argv = strtoargv(arg,&argc);
412 p_Rev = malloc(sizeof(struct rev_info));
413 memset(p_Rev,0,sizeof(struct rev_info));
415 p_Rev->pPrivate = argv;
416 *diff = (GIT_DIFF)p_Rev;
418 init_revisions(p_Rev, g_prefix);
419 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
420 p_Rev->abbrev = 0;
421 p_Rev->diff = 1;
422 argc = setup_revisions(argc, argv, p_Rev, NULL);
424 return 0;
426 int git_close_diff(GIT_DIFF handle)
428 git_diff_flush(handle);
429 if(handle)
431 struct rev_info *p_Rev;
432 p_Rev=(struct rev_info *)handle;
433 if(p_Rev->pPrivate)
434 free(p_Rev->pPrivate);
435 free(handle);
437 return 0;
439 int git_diff_flush(GIT_DIFF diff)
441 struct diff_queue_struct *q = &diff_queued_diff;
442 struct rev_info *p_Rev;
443 int i;
444 p_Rev = (struct rev_info *)diff;
446 if(q->nr == 0)
447 return 0;
449 for (i = 0; i < q->nr; i++)
450 diff_free_filepair(q->queue[i]);
452 if(q->queue)
454 free(q->queue);
455 q->queue = NULL;
456 q->nr = q->alloc = 0;
459 if (p_Rev->diffopt.close_file)
460 fclose(p_Rev->diffopt.close_file);
462 free_diffstat_info(&p_Rev->diffstat);
465 int git_root_diff(GIT_DIFF diff, GIT_HASH hash,GIT_FILE *file, int *count)
467 int ret;
468 struct rev_info *p_Rev;
469 int i;
470 struct diff_queue_struct *q = &diff_queued_diff;
472 p_Rev = (struct rev_info *)diff;
474 ret=diff_root_tree_sha1(hash, "", &p_Rev->diffopt);
476 if(ret)
477 return ret;
479 diffcore_std(&p_Rev->diffopt);
481 memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));
482 for (i = 0; i < q->nr; i++) {
483 struct diff_filepair *p = q->queue[i];
484 //if (check_pair_status(p))
485 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);
488 if(file)
489 *file = q;
490 if(count)
491 *count = q->nr;
493 return 0;
496 int git_diff(GIT_DIFF diff, GIT_HASH hash1, GIT_HASH hash2, GIT_FILE * file, int *count)
498 struct rev_info *p_Rev;
499 int ret;
500 int i;
501 struct diff_queue_struct *q = &diff_queued_diff;
503 p_Rev = (struct rev_info *)diff;
505 ret = diff_tree_sha1(hash1,hash2,"",&p_Rev->diffopt);
506 if( ret )
507 return ret;
509 diffcore_std(&p_Rev->diffopt);
511 memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));
512 for (i = 0; i < q->nr; i++) {
513 struct diff_filepair *p = q->queue[i];
514 //if (check_pair_status(p))
515 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);
518 if(file)
519 *file = q;
520 if(count)
521 *count = q->nr;
522 return 0;
525 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)
527 struct diff_queue_struct *q = &diff_queued_diff;
528 struct rev_info *p_Rev;
529 p_Rev = (struct rev_info *)diff;
531 q = (struct diff_queue_struct *)file;
532 if(file == 0)
533 return -1;
534 if(i>=q->nr)
535 return -1;
537 if(newname)
538 *newname = q->queue[i]->two->path;
540 if(oldname)
541 *oldname = q->queue[i]->one->path;
543 if(status)
544 *status = q->queue[i]->status;
546 if(p_Rev->diffstat.files)
548 int j;
549 for(j=0;j<p_Rev->diffstat.nr;j++)
551 if(strcmp(*newname,p_Rev->diffstat.files[j]->name)==0)
552 break;
554 if( j== p_Rev->diffstat.nr)
556 *IsBin=1;
557 *inc=0;
558 *dec=0;
559 return 0;
561 if(IsBin)
562 *IsBin = p_Rev->diffstat.files[j]->is_binary;
563 if(inc)
564 *inc = p_Rev->diffstat.files[j]->added;
565 if(dec)
566 *dec = p_Rev->diffstat.files[j]->deleted;
567 }else
569 *IsBin=1;
570 *inc=0;
571 *dec=0;
574 return 0;