Fix gitdll log crash because cmd_log_init add new parameter
[TortoiseGit.git] / ext / gitdll / gitdll.c
blobe4992c51651fbe82fdd49a16d3b834535c8faad0
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 #include "dir.h"
15 const char git_version_string[] = GIT_VERSION;
18 #if 0
20 // This is an example of an exported variable
21 GITDLL_API int ngitdll=0;
23 // This is an example of an exported function.
24 GITDLL_API int fngitdll(void)
26 return 42;
29 // This is the constructor of a class that has been exported.
30 // see gitdll.h for the class definition
31 Cgitdll::Cgitdll()
33 return;
35 #endif
37 extern char g_last_error[];
38 void * g_prefix;
40 char * get_git_last_error()
42 return g_last_error;
45 extern void die_dll(const char *err, va_list params);
47 void dll_entry()
49 set_die_routine(die_dll);
52 int git_get_sha1(const char *name, GIT_HASH sha1)
54 return get_sha1(name,sha1);
57 static int convert_slash(char * path)
59 while(*path)
61 if(*path == '\\' )
62 *path = '/';
63 path++;
67 int git_init()
69 char *home;
70 char path[MAX_PATH+1];
71 char *prefix;
72 int ret;
73 size_t homesize,size,httpsize;
75 _fmode = _O_BINARY;
76 _setmode(_fileno(stdin), _O_BINARY);
77 _setmode(_fileno(stdout), _O_BINARY);
78 _setmode(_fileno(stderr), _O_BINARY);
80 // set HOME if not set already
81 getenv_s(&homesize, NULL, 0, "HOME");
82 if (!homesize)
84 _dupenv_s(&home,&size,"USERPROFILE");
85 _putenv_s("HOME",home);
86 free(home);
88 GetModuleFileName(NULL, path, MAX_PATH);
89 convert_slash(path);
91 git_extract_argv0_path(path);
92 g_prefix = prefix = setup_git_directory();
93 ret = git_config(git_default_config, NULL);
95 if (!homesize)
97 _putenv_s("HOME","");/* clear home evironment to avoid affact third part software*/
100 return ret;
103 static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR *author, char *pbuff)
105 char *end;
107 author->Name=pbuff;
108 end=strchr(pbuff,'<');
109 if( end == 0)
111 return -1;
113 author->NameSize = end - pbuff - 1;
115 pbuff = end +1;
116 end = strchr(pbuff, '>');
117 if( end == 0)
118 return -1;
120 author->Email = pbuff ;
121 author->EmailSize = end - pbuff;
123 pbuff = end + 2;
125 author->Date = atol(pbuff);
126 end = strchr(pbuff, ' ');
127 if( end == 0 )
128 return -1;
130 pbuff=end;
131 author->TimeZone = atol(pbuff);
133 return 0;
136 int git_parse_commit(GIT_COMMIT *commit)
138 int ret = 0;
139 char *pbuf;
140 char *end;
141 struct commit *p;
143 p= (struct commit *)commit->m_pGitCommit;
145 memcpy(commit->m_hash,p->object.sha1,GIT_HASH_SIZE);
147 commit->m_Encode = NULL;
148 commit->m_EncodeSize = 0;
150 if(p->buffer == NULL)
151 return -1;
153 pbuf = p->buffer;
154 while(pbuf)
156 if( strncmp(pbuf,"author",6) == 0)
158 ret = git_parse_commit_author(&commit->m_Author,pbuf + 7);
159 if(ret)
160 return ret;
162 if( strncmp(pbuf, "committer",9) == 0)
164 ret = git_parse_commit_author(&commit->m_Committer,pbuf + 10);
165 if(ret)
166 return ret;
168 pbuf = strchr(pbuf,'\n');
169 if(pbuf == NULL)
170 return -1;
172 while((*pbuf) && (*pbuf == '\n'))
173 pbuf ++;
175 if( strncmp(pbuf, "encoding",8) == 0 )
177 pbuf += 9;
178 commit->m_Encode=pbuf;
179 end = strchr(pbuf,'\n');
180 commit->m_EncodeSize=end -pbuf;
182 pbuf = end +1;
183 while((*pbuf) && (*pbuf == '\n'))
184 pbuf ++;
186 commit->m_Subject=pbuf;
187 end = strchr(pbuf,'\n');
188 if( end == 0)
189 commit->m_SubjectSize = strlen(pbuf);
190 else
192 commit->m_SubjectSize = end - pbuf;
193 pbuf = end +1;
194 commit->m_Body = pbuf;
195 commit->m_BodySize = strlen(pbuf);
196 return 0;
201 pbuf = strchr(pbuf,'\n');
202 if(pbuf)
203 pbuf ++;
208 int git_get_commit_from_hash(GIT_COMMIT *commit, GIT_HASH hash)
210 int ret = 0;
212 struct commit *p;
214 memset(commit,0,sizeof(GIT_COMMIT));
216 commit->m_pGitCommit = p = lookup_commit(hash);
218 if(commit == NULL)
219 return -1;
221 if(p == NULL)
222 return -1;
224 ret = parse_commit(p);
225 if( ret )
226 return ret;
228 return git_parse_commit(commit);
231 int git_get_commit_first_parent(GIT_COMMIT *commit,GIT_COMMIT_LIST *list)
233 struct commit *p = commit->m_pGitCommit;
235 if(list == NULL)
236 return -1;
238 *list = (GIT_COMMIT_LIST*)p->parents;
239 return 0;
241 int git_get_commit_next_parent(GIT_COMMIT_LIST *list, GIT_HASH hash)
243 struct commit_list *l = *(struct commit_list **)list;
244 if(list == NULL || l==NULL)
245 return -1;
247 if(hash)
248 memcpy(hash, l->item->object.sha1, GIT_HASH_SIZE);
250 *list = (GIT_COMMIT_LIST *)l->next;
251 return 0;
256 int git_free_commit(GIT_COMMIT *commit)
258 struct commit *p = commit->m_pGitCommit;
260 if( p->parents)
261 free_commit_list(p->parents);
263 if( p->buffer )
265 free(p->buffer);
266 p->buffer=NULL;
267 p->object.parsed=0;
268 p->parents=0;
269 p->tree=0;
271 memset(commit,0,sizeof(GIT_COMMIT));
272 return 0;
275 char **strtoargv(char *arg, int *size)
277 int count=0;
278 char *p=arg;
279 char **argv;
281 int i=0;
282 while(*p)
284 if(*p == '\\')
285 *p='/';
286 p++;
288 p=arg;
290 while(*p)
292 if(*p == ' ')
293 count ++;
294 p++;
297 argv=malloc(strlen(arg)+1 + (count +2)*sizeof(void*));
298 p=(char*)(argv+count+2);
300 while(*arg)
302 if(*arg == '"')
304 argv[i] = p;
305 arg++;
306 *p=*arg;
307 while(*arg && *arg!= '"')
308 *p++=*arg++;
309 *p++=0;
310 arg++;
311 i++;
312 if(*arg == 0)
313 break;
315 if(*arg != ' ')
317 argv[i]=p;
318 while(*arg && *arg !=' ')
319 *p++ = *arg++;
320 i++;
321 *p++=0;
323 arg++;
325 argv[i]=NULL;
326 *size = i;
327 return argv;
329 int git_open_log(GIT_LOG * handle, char * arg)
331 struct rev_info *p_Rev;
332 int size;
333 char ** argv=0;
334 int argc=0;
335 int i=0;
336 struct setup_revision_opt opt;
338 /* clear flags */
339 unsigned int obj_size = get_max_object_index();
340 for(i =0; i<obj_size; i++)
342 struct object *ob= get_indexed_object(i);
343 if(ob)
344 ob->flags=0;
347 if(arg != NULL)
348 argv = strtoargv(arg,&argc);
350 p_Rev = malloc(sizeof(struct rev_info));
351 memset(p_Rev,0,sizeof(struct rev_info));
353 if(p_Rev == NULL)
354 return -1;
356 init_revisions(p_Rev, g_prefix);
357 p_Rev->diff = 1;
359 memset(&opt, 0, sizeof(opt));
360 opt.def = "HEAD";
362 cmd_log_init(argc, argv, g_prefix,p_Rev,&opt);
364 p_Rev->pPrivate = argv;
365 *handle = p_Rev;
366 return 0;
369 int git_get_log_firstcommit(GIT_LOG handle)
371 return prepare_revision_walk(handle);
374 int git_get_log_estimate_commit_count(GIT_LOG handle)
376 struct rev_info *p_Rev;
377 p_Rev=(struct rev_info *)handle;
379 return estimate_commit_count(p_Rev, p_Rev->commits);
382 int git_get_log_nextcommit(GIT_LOG handle, GIT_COMMIT *commit)
384 int ret =0;
386 if(commit == NULL)
387 return -1;
389 memset(commit, 0, sizeof(GIT_COMMIT));
391 commit->m_pGitCommit = get_revision(handle);
392 if( commit->m_pGitCommit == NULL)
393 return -2;
395 ret=git_parse_commit(commit);
396 if(ret)
397 return ret;
399 return 0;
402 int git_close_log(GIT_LOG handle)
404 if(handle)
406 struct rev_info *p_Rev;
407 p_Rev=(struct rev_info *)handle;
408 if(p_Rev->pPrivate)
409 free(p_Rev->pPrivate);
410 free(handle);
413 return 0;
416 int git_open_diff(GIT_DIFF *diff, char * arg)
418 struct rev_info *p_Rev;
419 int size;
420 char ** argv=0;
421 int argc=0;
423 if(arg != NULL)
424 argv = strtoargv(arg,&argc);
426 p_Rev = malloc(sizeof(struct rev_info));
427 memset(p_Rev,0,sizeof(struct rev_info));
429 p_Rev->pPrivate = argv;
430 *diff = (GIT_DIFF)p_Rev;
432 init_revisions(p_Rev, g_prefix);
433 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
434 p_Rev->abbrev = 0;
435 p_Rev->diff = 1;
436 argc = setup_revisions(argc, argv, p_Rev, NULL);
438 return 0;
440 int git_close_diff(GIT_DIFF handle)
442 git_diff_flush(handle);
443 if(handle)
445 struct rev_info *p_Rev;
446 p_Rev=(struct rev_info *)handle;
447 if(p_Rev->pPrivate)
448 free(p_Rev->pPrivate);
449 free(handle);
451 return 0;
453 int git_diff_flush(GIT_DIFF diff)
455 struct diff_queue_struct *q = &diff_queued_diff;
456 struct rev_info *p_Rev;
457 int i;
458 p_Rev = (struct rev_info *)diff;
460 if(q->nr == 0)
461 return 0;
463 for (i = 0; i < q->nr; i++)
464 diff_free_filepair(q->queue[i]);
466 if(q->queue)
468 free(q->queue);
469 q->queue = NULL;
470 q->nr = q->alloc = 0;
473 if (p_Rev->diffopt.close_file)
474 fclose(p_Rev->diffopt.close_file);
476 free_diffstat_info(&p_Rev->diffstat);
479 int git_root_diff(GIT_DIFF diff, GIT_HASH hash,GIT_FILE *file, int *count)
481 int ret;
482 struct rev_info *p_Rev;
483 int i;
484 struct diff_queue_struct *q = &diff_queued_diff;
486 p_Rev = (struct rev_info *)diff;
488 ret=diff_root_tree_sha1(hash, "", &p_Rev->diffopt);
490 if(ret)
491 return ret;
493 diffcore_std(&p_Rev->diffopt);
495 memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));
496 for (i = 0; i < q->nr; i++) {
497 struct diff_filepair *p = q->queue[i];
498 //if (check_pair_status(p))
499 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);
502 if(file)
503 *file = q;
504 if(count)
505 *count = q->nr;
507 return 0;
510 int git_diff(GIT_DIFF diff, GIT_HASH hash1, GIT_HASH hash2, GIT_FILE * file, int *count)
512 struct rev_info *p_Rev;
513 int ret;
514 int i;
515 struct diff_queue_struct *q = &diff_queued_diff;
517 p_Rev = (struct rev_info *)diff;
519 ret = diff_tree_sha1(hash1,hash2,"",&p_Rev->diffopt);
520 if( ret )
521 return ret;
523 diffcore_std(&p_Rev->diffopt);
525 memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));
526 for (i = 0; i < q->nr; i++) {
527 struct diff_filepair *p = q->queue[i];
528 //if (check_pair_status(p))
529 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);
532 if(file)
533 *file = q;
534 if(count)
535 *count = q->nr;
536 return 0;
539 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)
541 struct diff_queue_struct *q = &diff_queued_diff;
542 struct rev_info *p_Rev;
543 p_Rev = (struct rev_info *)diff;
545 q = (struct diff_queue_struct *)file;
546 if(file == 0)
547 return -1;
548 if(i>=q->nr)
549 return -1;
551 if(newname)
552 *newname = q->queue[i]->two->path;
554 if(oldname)
555 *oldname = q->queue[i]->one->path;
557 if(status)
558 *status = q->queue[i]->status;
560 if(p_Rev->diffstat.files)
562 int j;
563 for(j=0;j<p_Rev->diffstat.nr;j++)
565 if(strcmp(*newname,p_Rev->diffstat.files[j]->name)==0)
566 break;
568 if( j== p_Rev->diffstat.nr)
570 *IsBin=1;
571 *inc=0;
572 *dec=0;
573 return 0;
575 if(IsBin)
576 *IsBin = p_Rev->diffstat.files[j]->is_binary;
577 if(inc)
578 *inc = p_Rev->diffstat.files[j]->added;
579 if(dec)
580 *dec = p_Rev->diffstat.files[j]->deleted;
581 }else
583 *IsBin=1;
584 *inc=0;
585 *dec=0;
588 return 0;
591 int git_read_tree(GIT_HASH hash,read_tree_fn_t fn, void *context)
593 struct tree * root;
594 int ret;
595 reprepare_packed_git();
596 root = parse_tree_indirect(hash);
598 if (!root)
600 free_all_pack();
601 return -1;
603 ret = read_tree_recursive(root,NULL,NULL,0,NULL,fn,context);
604 free_all_pack();
605 return ret;
608 int git_add_exclude(const char *string, const char *base,
609 int baselen, struct exclude_list *which)
611 add_exclude(string, base, baselen, which);
612 return 0;
615 int git_create_exclude_list(EXCLUDE_LIST *which)
617 *which = malloc(sizeof(struct exclude_list));
618 memset(*which,0,sizeof(struct exclude_list));
619 return 0;
622 int git_free_exclude_list(EXCLUDE_LIST which)
624 int i=0;
625 struct exclude_list *p = (struct exclude_list *) which;
627 for(i=0; i<p->nr;i++)
629 free(p->excludes[i]);
631 free(p->excludes);
632 free(p);
635 int git_check_excluded_1(const char *pathname,
636 int pathlen, const char *basename, int *dtype,
637 EXCLUDE_LIST el)
639 return excluded_from_list(pathname, pathlen, basename,dtype,el);