some spaces-tabs code cleanup
[TortoiseGit.git] / ext / gitdll / gitdll.c
blob85db997902c577e0f5f903e9c40ca46345927281
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"
14 #include "builtin.h"
15 #include "exec_cmd.h"
16 #include "cache.h"
17 #include "quote.h"
18 #include "run-command.h"
20 const char git_version_string[] = GIT_VERSION;
23 #if 0
25 // This is an example of an exported variable
26 GITDLL_API int ngitdll=0;
28 // This is an example of an exported function.
29 GITDLL_API int fngitdll(void)
31 return 42;
34 // This is the constructor of a class that has been exported.
35 // see gitdll.h for the class definition
36 Cgitdll::Cgitdll()
38 return;
40 #endif
42 extern char g_last_error[];
43 void * g_prefix;
45 char * get_git_last_error()
47 return g_last_error;
50 extern void die_dll(const char *err, va_list params);
52 void dll_entry()
54 set_die_routine(die_dll);
57 int git_get_sha1(const char *name, GIT_HASH sha1)
59 return get_sha1(name,sha1);
62 static int convert_slash(char * path)
64 while(*path)
66 if(*path == '\\' )
67 *path = '/';
68 path++;
70 return 0;
73 int git_init()
75 char *home;
76 char path[MAX_PATH+1];
77 char *prefix;
78 int ret;
79 size_t homesize,size;
81 _fmode = _O_BINARY;
82 _setmode(_fileno(stdin), _O_BINARY);
83 _setmode(_fileno(stdout), _O_BINARY);
84 _setmode(_fileno(stderr), _O_BINARY);
86 // set HOME if not set already
87 getenv_s(&homesize, NULL, 0, "HOME");
88 if (!homesize)
90 _dupenv_s(&home,&size,"USERPROFILE");
91 _putenv_s("HOME",home);
92 free(home);
94 GetModuleFileName(NULL, path, MAX_PATH);
95 convert_slash(path);
97 git_extract_argv0_path(path);
98 g_prefix = prefix = setup_git_directory();
99 ret = git_config(git_default_config, NULL);
101 if (!homesize)
103 _putenv_s("HOME","");/* clear home evironment to avoid affact third part software*/
106 return ret;
109 static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR *author, char *pbuff)
111 char *end;
113 author->Name=pbuff;
114 end=strchr(pbuff,'<');
115 if( end == 0)
117 return -1;
119 author->NameSize = end - pbuff - 1;
121 pbuff = end +1;
122 end = strchr(pbuff, '>');
123 if( end == 0)
124 return -1;
126 author->Email = pbuff ;
127 author->EmailSize = end - pbuff;
129 pbuff = end + 2;
131 author->Date = atol(pbuff);
132 end = strchr(pbuff, ' ');
133 if( end == 0 )
134 return -1;
136 pbuff=end;
137 author->TimeZone = atol(pbuff);
139 return 0;
142 int git_parse_commit(GIT_COMMIT *commit)
144 int ret = 0;
145 char *pbuf;
146 char *end;
147 struct commit *p;
149 p= (struct commit *)commit->m_pGitCommit;
151 memcpy(commit->m_hash,p->object.sha1,GIT_HASH_SIZE);
153 commit->m_Encode = NULL;
154 commit->m_EncodeSize = 0;
156 if(p->buffer == NULL)
157 return -1;
159 pbuf = p->buffer;
160 while(pbuf)
162 if( strncmp(pbuf,"author",6) == 0)
164 ret = git_parse_commit_author(&commit->m_Author,pbuf + 7);
165 if(ret)
166 return ret;
168 if( strncmp(pbuf, "committer",9) == 0)
170 ret = git_parse_commit_author(&commit->m_Committer,pbuf + 10);
171 if(ret)
172 return ret;
174 pbuf = strchr(pbuf,'\n');
175 if(pbuf == NULL)
176 return -1;
178 pbuf ++;
180 if( strncmp(pbuf, "encoding",8) == 0 )
182 pbuf += 9;
183 commit->m_Encode=pbuf;
184 end = strchr(pbuf,'\n');
185 commit->m_EncodeSize=end -pbuf;
187 pbuf = end +1;
190 while((*pbuf) && (*pbuf == '\n'))
191 pbuf ++;
193 commit->m_Subject=pbuf;
194 end = strchr(pbuf,'\n');
195 if( end == 0)
196 commit->m_SubjectSize = strlen(pbuf);
197 else
199 commit->m_SubjectSize = end - pbuf;
200 pbuf = end +1;
201 commit->m_Body = pbuf;
202 commit->m_BodySize = strlen(pbuf);
203 return 0;
208 pbuf = strchr(pbuf,'\n');
209 if(pbuf)
210 pbuf ++;
212 return 0;
215 int git_get_commit_from_hash(GIT_COMMIT *commit, GIT_HASH hash)
217 int ret = 0;
219 struct commit *p;
221 memset(commit,0,sizeof(GIT_COMMIT));
223 commit->m_pGitCommit = p = lookup_commit(hash);
225 if(commit == NULL)
226 return -1;
228 if(p == NULL)
229 return -1;
231 ret = parse_commit(p);
232 if( ret )
233 return ret;
235 return git_parse_commit(commit);
238 int git_get_commit_first_parent(GIT_COMMIT *commit,GIT_COMMIT_LIST *list)
240 struct commit *p = commit->m_pGitCommit;
242 if(list == NULL)
243 return -1;
245 *list = (GIT_COMMIT_LIST*)p->parents;
246 return 0;
248 int git_get_commit_next_parent(GIT_COMMIT_LIST *list, GIT_HASH hash)
250 struct commit_list *l = *(struct commit_list **)list;
251 if(list == NULL || l==NULL)
252 return -1;
254 if(hash)
255 memcpy(hash, l->item->object.sha1, GIT_HASH_SIZE);
257 *list = (GIT_COMMIT_LIST *)l->next;
258 return 0;
263 int git_free_commit(GIT_COMMIT *commit)
265 struct commit *p = commit->m_pGitCommit;
267 if( p->parents)
268 free_commit_list(p->parents);
270 if( p->buffer )
272 free(p->buffer);
273 p->buffer=NULL;
274 p->object.parsed=0;
275 p->parents=0;
276 p->tree=0;
278 memset(commit,0,sizeof(GIT_COMMIT));
279 return 0;
282 char **strtoargv(char *arg, int *size)
284 int count=0;
285 char *p=arg;
286 char **argv;
288 int i=0;
289 while(*p)
291 if(*p == '\\')
292 *p='/';
293 p++;
295 p=arg;
297 while(*p)
299 if(*p == ' ')
300 count ++;
301 p++;
304 argv=malloc(strlen(arg)+1 + (count +2)*sizeof(void*));
305 p=(char*)(argv+count+2);
307 while(*arg)
309 if(*arg != ' ')
311 char space=' ';
312 argv[i]=p;
314 while(*arg)
316 if(*arg == '"')
318 arg++;
319 if(space == ' ')
320 space = '"';
321 else
322 space = ' ';
324 if((*arg == space) || (*arg == 0))
325 break;
327 *p++ = *arg++;
329 i++;
330 *p++=0;
332 if(*arg == 0)
333 break;
334 arg++;
336 argv[i]=NULL;
337 *size = i;
338 return argv;
340 int git_open_log(GIT_LOG * handle, char * arg)
342 struct rev_info *p_Rev;
343 char ** argv=0;
344 int argc=0;
345 unsigned int i=0;
346 struct setup_revision_opt opt;
348 /* clear flags */
349 unsigned int obj_size = get_max_object_index();
350 for(i =0; i<obj_size; i++)
352 struct object *ob= get_indexed_object(i);
353 if(ob)
354 ob->flags=0;
357 if(arg != NULL)
358 argv = strtoargv(arg,&argc);
360 p_Rev = malloc(sizeof(struct rev_info));
361 memset(p_Rev,0,sizeof(struct rev_info));
363 if(p_Rev == NULL)
364 return -1;
366 init_revisions(p_Rev, g_prefix);
367 p_Rev->diff = 1;
369 memset(&opt, 0, sizeof(opt));
370 opt.def = "HEAD";
372 cmd_log_init(argc, argv, g_prefix,p_Rev,&opt);
374 p_Rev->pPrivate = argv;
375 *handle = p_Rev;
376 return 0;
379 int git_get_log_firstcommit(GIT_LOG handle)
381 return prepare_revision_walk(handle);
384 int git_get_log_estimate_commit_count(GIT_LOG handle)
386 struct rev_info *p_Rev;
387 p_Rev=(struct rev_info *)handle;
389 return estimate_commit_count(p_Rev, p_Rev->commits);
392 int git_get_log_nextcommit(GIT_LOG handle, GIT_COMMIT *commit)
394 int ret =0;
396 if(commit == NULL)
397 return -1;
399 memset(commit, 0, sizeof(GIT_COMMIT));
401 commit->m_pGitCommit = get_revision(handle);
402 if( commit->m_pGitCommit == NULL)
403 return -2;
405 ret=git_parse_commit(commit);
406 if(ret)
407 return ret;
409 return 0;
412 struct notes_tree **display_notes_trees;
413 int git_close_log(GIT_LOG handle)
415 if(handle)
417 struct rev_info *p_Rev;
418 p_Rev=(struct rev_info *)handle;
419 if(p_Rev->pPrivate)
420 free(p_Rev->pPrivate);
421 free(handle);
424 free_notes(*display_notes_trees);
425 display_notes_trees = 0;
426 return 0;
429 int git_open_diff(GIT_DIFF *diff, char * arg)
431 struct rev_info *p_Rev;
432 char ** argv=0;
433 int argc=0;
435 if(arg != NULL)
436 argv = strtoargv(arg,&argc);
438 p_Rev = malloc(sizeof(struct rev_info));
439 memset(p_Rev,0,sizeof(struct rev_info));
441 p_Rev->pPrivate = argv;
442 *diff = (GIT_DIFF)p_Rev;
444 init_revisions(p_Rev, g_prefix);
445 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
446 p_Rev->abbrev = 0;
447 p_Rev->diff = 1;
448 argc = setup_revisions(argc, argv, p_Rev, NULL);
450 return 0;
452 int git_close_diff(GIT_DIFF handle)
454 git_diff_flush(handle);
455 if(handle)
457 struct rev_info *p_Rev;
458 p_Rev=(struct rev_info *)handle;
459 if(p_Rev->pPrivate)
460 free(p_Rev->pPrivate);
461 free(handle);
463 return 0;
465 int git_diff_flush(GIT_DIFF diff)
467 struct diff_queue_struct *q = &diff_queued_diff;
468 struct rev_info *p_Rev;
469 int i;
470 p_Rev = (struct rev_info *)diff;
472 if(q->nr == 0)
473 return 0;
475 for (i = 0; i < q->nr; i++)
476 diff_free_filepair(q->queue[i]);
478 if(q->queue)
480 free(q->queue);
481 q->queue = NULL;
482 q->nr = q->alloc = 0;
485 if (p_Rev->diffopt.close_file)
486 fclose(p_Rev->diffopt.close_file);
488 free_diffstat_info(&p_Rev->diffstat);
489 return 0;
492 int git_root_diff(GIT_DIFF diff, GIT_HASH hash,GIT_FILE *file, int *count, int isstat)
494 int ret;
495 struct rev_info *p_Rev;
496 int i;
497 struct diff_queue_struct *q = &diff_queued_diff;
499 p_Rev = (struct rev_info *)diff;
501 ret=diff_root_tree_sha1(hash, "", &p_Rev->diffopt);
503 if(ret)
504 return ret;
506 if(isstat)
508 diffcore_std(&p_Rev->diffopt);
510 memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));
511 for (i = 0; i < q->nr; i++) {
512 struct diff_filepair *p = q->queue[i];
513 //if (check_pair_status(p))
514 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);
517 if(file)
518 *file = q;
519 if(count)
520 *count = q->nr;
522 return 0;
525 int git_diff(GIT_DIFF diff, GIT_HASH hash1, GIT_HASH hash2, GIT_FILE * file, int *count,int isstat)
527 struct rev_info *p_Rev;
528 int ret;
529 int i;
530 struct diff_queue_struct *q = &diff_queued_diff;
532 p_Rev = (struct rev_info *)diff;
534 ret = diff_tree_sha1(hash1,hash2,"",&p_Rev->diffopt);
535 if( ret )
536 return ret;
538 if(isstat)
540 diffcore_std(&p_Rev->diffopt);
541 memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));
542 for (i = 0; i < q->nr; i++) {
543 struct diff_filepair *p = q->queue[i];
544 //if (check_pair_status(p))
545 diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);
548 if(file)
549 *file = q;
550 if(count)
551 *count = q->nr;
552 return 0;
555 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)
557 struct diff_queue_struct *q = &diff_queued_diff;
558 struct rev_info *p_Rev;
559 p_Rev = (struct rev_info *)diff;
561 q = (struct diff_queue_struct *)file;
562 if(file == 0)
563 return -1;
564 if(i>=q->nr)
565 return -1;
567 if(newname)
568 *newname = q->queue[i]->two->path;
570 if(oldname)
571 *oldname = q->queue[i]->one->path;
573 if(status)
574 *status = q->queue[i]->status;
576 if(p_Rev->diffstat.files)
578 int j;
579 for(j=0;j<p_Rev->diffstat.nr;j++)
581 if(strcmp(*newname,p_Rev->diffstat.files[j]->name)==0)
582 break;
584 if( j== p_Rev->diffstat.nr)
586 *IsBin=1;
587 *inc=0;
588 *dec=0;
589 return 0;
591 if(IsBin)
592 *IsBin = p_Rev->diffstat.files[j]->is_binary;
593 if(inc)
594 *inc = p_Rev->diffstat.files[j]->added;
595 if(dec)
596 *dec = p_Rev->diffstat.files[j]->deleted;
597 }else
599 *IsBin=1;
600 *inc=0;
601 *dec=0;
604 return 0;
607 int git_read_tree(GIT_HASH hash,read_tree_fn_t fn, void *context)
609 struct tree * root;
610 int ret;
611 reprepare_packed_git();
612 root = parse_tree_indirect(hash);
614 if (!root)
616 free_all_pack();
617 return -1;
619 ret = read_tree_recursive(root,NULL,NULL,0,NULL,fn,context);
620 free_all_pack();
621 return ret;
624 int git_add_exclude(const char *string, const char *base,
625 int baselen, struct exclude_list *which)
627 add_exclude(string, base, baselen, which);
628 return 0;
631 int git_create_exclude_list(EXCLUDE_LIST *which)
633 *which = malloc(sizeof(struct exclude_list));
634 memset(*which,0,sizeof(struct exclude_list));
635 return 0;
638 int git_free_exclude_list(EXCLUDE_LIST which)
640 int i=0;
641 struct exclude_list *p = (struct exclude_list *) which;
643 for(i=0; i<p->nr;i++)
645 free(p->excludes[i]);
647 free(p->excludes);
648 free(p);
649 return 0;
652 int git_check_excluded_1(const char *pathname,
653 int pathlen, const char *basename, int *dtype,
654 EXCLUDE_LIST el)
656 return excluded_from_list(pathname, pathlen, basename,dtype,el);
659 int git_get_notes(GIT_HASH hash, char **p_note)
661 struct strbuf sb;
662 size_t size;
663 strbuf_init(&sb,0);
664 format_display_notes(hash, &sb, "utf-8", 0);
665 *p_note = strbuf_detach(&sb,&size);
667 return 0;
670 struct cmd_struct {
671 const char *cmd;
672 int (*fn)(int, const char **, const char *);
673 int option;
676 #define RUN_SETUP (1<<0)
677 #define USE_PAGER (1<<1)
679 * require working tree to be present -- anything uses this needs
680 * RUN_SETUP for reading from the configuration file.
682 #define NEED_WORK_TREE (1<<2)
684 const char git_usage_string[] =
685 "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
686 " [-p|--paginate|--no-pager] [--no-replace-objects]\n"
687 " [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
688 " [-c name=value] [--help]\n"
689 " COMMAND [ARGS]";
691 const char git_more_info_string[] =
692 "See 'git help COMMAND' for more information on a specific command.";
694 /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
695 int check_pager_config(const char *cmd)
697 return 0;
701 int git_run_cmd(char *cmd, char *arg)
704 int i=0;
705 char ** argv=0;
706 int argc=0;
708 static struct cmd_struct commands[] = {
709 { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
710 { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
711 { "annotate", cmd_annotate, RUN_SETUP },
712 { "apply", cmd_apply },
713 { "archive", cmd_archive },
714 { "bisect--helper", cmd_bisect__helper, RUN_SETUP | NEED_WORK_TREE },
715 { "blame", cmd_blame, RUN_SETUP },
716 { "branch", cmd_branch, RUN_SETUP },
717 { "bundle", cmd_bundle },
718 { "cat-file", cmd_cat_file, RUN_SETUP },
719 { "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
720 { "checkout-index", cmd_checkout_index,
721 RUN_SETUP | NEED_WORK_TREE},
722 { "check-ref-format", cmd_check_ref_format },
723 { "check-attr", cmd_check_attr, RUN_SETUP },
724 { "cherry", cmd_cherry, RUN_SETUP },
725 { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
726 { "clone", cmd_clone },
727 { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
728 { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
729 { "commit-tree", cmd_commit_tree, RUN_SETUP },
730 { "config", cmd_config },
731 { "count-objects", cmd_count_objects, RUN_SETUP },
732 { "describe", cmd_describe, RUN_SETUP },
733 { "diff", cmd_diff },
734 { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
735 { "diff-index", cmd_diff_index, RUN_SETUP },
736 { "diff-tree", cmd_diff_tree, RUN_SETUP },
737 { "fast-export", cmd_fast_export, RUN_SETUP },
738 { "fetch", cmd_fetch, RUN_SETUP },
739 { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
740 { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
741 { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
742 { "format-patch", cmd_format_patch, RUN_SETUP },
743 { "fsck", cmd_fsck, RUN_SETUP },
744 { "fsck-objects", cmd_fsck, RUN_SETUP },
745 { "gc", cmd_gc, RUN_SETUP },
746 { "get-tar-commit-id", cmd_get_tar_commit_id },
747 { "grep", cmd_grep },
748 { "hash-object", cmd_hash_object },
749 { "help", cmd_help },
750 { "index-pack", cmd_index_pack },
751 { "init", cmd_init_db },
752 { "init-db", cmd_init_db },
753 { "log", cmd_log, RUN_SETUP },
754 { "ls-files", cmd_ls_files, RUN_SETUP },
755 { "ls-tree", cmd_ls_tree, RUN_SETUP },
756 { "ls-remote", cmd_ls_remote },
757 { "mailinfo", cmd_mailinfo },
758 { "mailsplit", cmd_mailsplit },
759 { "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
760 { "merge-base", cmd_merge_base, RUN_SETUP },
761 { "merge-file", cmd_merge_file },
762 { "merge-index", cmd_merge_index, RUN_SETUP },
763 { "merge-ours", cmd_merge_ours, RUN_SETUP },
764 { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
765 { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
766 { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
767 { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
768 { "merge-tree", cmd_merge_tree, RUN_SETUP },
769 { "mktag", cmd_mktag, RUN_SETUP },
770 { "mktree", cmd_mktree, RUN_SETUP },
771 { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
772 { "name-rev", cmd_name_rev, RUN_SETUP },
773 { "notes", cmd_notes, RUN_SETUP },
774 { "pack-objects", cmd_pack_objects, RUN_SETUP },
775 { "pack-redundant", cmd_pack_redundant, RUN_SETUP },
776 { "patch-id", cmd_patch_id },
777 { "peek-remote", cmd_ls_remote },
778 { "pickaxe", cmd_blame, RUN_SETUP },
779 { "prune", cmd_prune, RUN_SETUP },
780 { "prune-packed", cmd_prune_packed, RUN_SETUP },
781 { "push", cmd_push, RUN_SETUP },
782 { "read-tree", cmd_read_tree, RUN_SETUP },
783 { "receive-pack", cmd_receive_pack },
784 { "reflog", cmd_reflog, RUN_SETUP },
785 { "remote", cmd_remote, RUN_SETUP },
786 { "replace", cmd_replace, RUN_SETUP },
787 { "repo-config", cmd_config },
788 { "rerere", cmd_rerere, RUN_SETUP },
789 { "reset", cmd_reset, RUN_SETUP },
790 { "rev-list", cmd_rev_list, RUN_SETUP },
791 { "rev-parse", cmd_rev_parse },
792 { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
793 { "rm", cmd_rm, RUN_SETUP },
794 { "send-pack", cmd_send_pack, RUN_SETUP },
795 { "shortlog", cmd_shortlog, USE_PAGER },
796 { "show-branch", cmd_show_branch, RUN_SETUP },
797 { "show", cmd_show, RUN_SETUP },
798 { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
799 { "stripspace", cmd_stripspace },
800 { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
801 { "tag", cmd_tag, RUN_SETUP },
802 { "tar-tree", cmd_tar_tree },
803 { "unpack-file", cmd_unpack_file, RUN_SETUP },
804 { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
805 { "update-index", cmd_update_index, RUN_SETUP },
806 { "update-ref", cmd_update_ref, RUN_SETUP },
807 { "update-server-info", cmd_update_server_info, RUN_SETUP },
808 { "upload-archive", cmd_upload_archive },
809 { "var", cmd_var },
810 { "verify-tag", cmd_verify_tag, RUN_SETUP },
811 { "version", cmd_version },
812 { "whatchanged", cmd_whatchanged, RUN_SETUP },
813 { "write-tree", cmd_write_tree, RUN_SETUP },
814 { "verify-pack", cmd_verify_pack },
815 { "show-ref", cmd_show_ref, RUN_SETUP },
816 { "pack-refs", cmd_pack_refs, RUN_SETUP },
819 git_init();
821 for(i=0;i< sizeof(commands) / sizeof(struct cmd_struct);i++)
823 if(strcmp(cmd,commands[i].cmd)==0)
825 int ret;
826 if(arg != NULL)
827 argv = strtoargv(arg,&argc);
829 ret = commands[i].fn(argc, argv, NULL);
831 if(argv)
832 free(argv);
834 return ret;
839 return -1;
842 int git_for_each_ref_in(const char * refname, each_ref_fn fn, void * data)
844 invalidate_cached_refs();
845 return for_each_ref_in(refname, fn, data);
848 const char *git_resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
850 invalidate_cached_refs();
851 return resolve_ref(ref,sha1,reading, flag);
853 int git_for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
855 return for_each_reflog_ent(ref,fn,cb_data);
858 int git_deref_tag(unsigned char *tagsha1, GIT_HASH refhash)
860 struct object *obj = NULL;
861 obj = parse_object(tagsha1);
862 if (!obj)
863 return -1;
865 if (obj->type == OBJ_TAG)
867 obj = deref_tag(obj, "", 0);
868 if (!obj)
869 return -1;
871 memcpy(refhash, obj->sha1, sizeof(GIT_HASH));
872 return 0;
875 return -1;
878 static int update_some(const unsigned char *sha1, const char *base, int baselen,
879 const char *pathname, unsigned mode, int stage, void *context)
881 struct cache_entry *ce;
883 ce = (struct cache_entry *)context;
885 if (S_ISDIR(mode))
886 return READ_TREE_RECURSIVE;
888 hashcpy(ce->sha1, sha1);
889 memcpy(ce->name, base, baselen);
890 memcpy(ce->name + baselen, pathname, strlen(pathname));
891 ce->ce_flags = create_ce_flags(strlen(pathname)+baselen, 0);
892 ce->ce_mode = create_ce_mode(mode);
894 return 0;
897 int git_checkout_file(const char *ref, const char *path, const char *outputpath)
899 struct cache_entry *ce;
900 int ret;
901 GIT_HASH sha1;
902 struct tree * root;
903 struct checkout state;
904 char *match[2];
905 ret = get_sha1(ref, sha1);
906 if(ret)
907 return ret;
909 reprepare_packed_git();
910 root = parse_tree_indirect(sha1);
912 if(!root)
913 return -1;
915 ce = xcalloc(1, cache_entry_size(strlen(path)));
917 match[0] = path;
918 match[1] = NULL;
919 ret = read_tree_recursive(root,"",0,0,match,update_some,ce);
921 if(ret)
923 free(ce);
924 return ret;
926 memset(&state, 0, sizeof(state));
927 state.force = 1;
928 state.refresh_cache = 0;
930 ret = write_entry(ce, outputpath, &state, 0);
931 free(ce);
932 return ret;
934 struct config_buf
936 char *buf;
937 char *key;
938 char *size;
939 int seen;
942 static int get_config(const char *key_, const char *value_, void *cb)
944 struct config_buf *buf;
945 buf=(struct config_buf*)cb;
946 if(strcmp(key_, buf->key))
947 return 0;
949 strncpy(buf->buf,value_,buf->size);
950 buf->seen = 1;
951 return 0;
954 int git_get_config(const char *key, char *buffer, int size, char *git_path)
956 char *local,*global,*system_wide,*p;
957 struct config_buf buf;
958 buf.buf=buffer;
959 buf.size=size;
960 buf.seen = 0;
961 buf.key = key;
963 local=global=system_wide=NULL;
965 //local = config_exclusive_filename;
966 if (!local) {
967 const char *home = getenv("HOME");
968 if(!home)
969 home=getenv("USERPROFILE");
971 local=p= git_pathdup("config");
972 if(git_path&&strlen(git_path))
974 local=xstrdup(mkpath("%s/%s", git_path, p));
975 free(p);
977 if (git_config_global() && home)
978 global = xstrdup(mkpath("%s/.gitconfig", home));
979 if (git_config_system())
980 system_wide = git_etc_gitconfig();
983 if ( !buf.seen)
984 git_config_from_file(get_config, local, &buf);
985 if (!buf.seen && global)
986 git_config_from_file(get_config, global, &buf);
987 if (!buf.seen && system_wide)
988 git_config_from_file(get_config, system_wide, &buf);
990 if(local)
991 free(local);
992 if(global)
993 free(global);
994 //if(system_wide)
995 // free(system_wide);
997 return !buf.seen;
1000 int get_set_config(const char *key, char *value, CONFIG_TYPE type,char *git_path)
1002 char *local,*global,*system_wide,*p;
1003 int ret;
1004 local=global=system_wide=NULL;
1006 //local = config_exclusive_filename;
1007 if (!local) {
1008 char *home = getenv("HOME");
1010 if(!home)
1011 home=getenv("USERPROFILE");
1013 local=p= git_pathdup("config");
1014 if(git_path&&strlen(git_path))
1016 local=xstrdup(mkpath("%s/%s", git_path, p));
1017 free(p);
1019 if (git_config_global() && home)
1020 global = xstrdup(mkpath("%s/.gitconfig", home));
1021 if (git_config_system())
1022 system_wide = git_etc_gitconfig();
1025 switch(type)
1027 case CONFIG_LOCAL:
1028 config_exclusive_filename = local;
1029 break;
1030 case CONFIG_GLOBAL:
1031 config_exclusive_filename = global;
1032 break;
1033 case CONFIG_SYSTEM:
1034 config_exclusive_filename = system_wide;
1035 break;
1036 default:
1037 config_exclusive_filename = NULL;
1038 break;
1041 if(!config_exclusive_filename)
1042 return -1;
1044 ret = git_config_set(key, value);
1046 if(local)
1047 free(local);
1048 if(global)
1049 free(global);
1050 //if(system_wide)
1051 // free(system_wide);
1053 return ret;