1 // gitdll.cpp : Defines the exported functions for the DLL application.
5 #include "git-compat-util.h"
18 #include "run-command.h"
20 const char git_version_string
[] = GIT_VERSION
;
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)
34 // This is the constructor of a class that has been exported.
35 // see gitdll.h for the class definition
42 extern char g_last_error
[];
45 char * get_git_last_error()
50 extern void die_dll(const char *err
, va_list params
);
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
)
75 char path
[MAX_PATH
+1];
78 size_t homesize
,size
,httpsize
;
81 _setmode(_fileno(stdin
), _O_BINARY
);
82 _setmode(_fileno(stdout
), _O_BINARY
);
83 _setmode(_fileno(stderr
), _O_BINARY
);
85 // set HOME if not set already
86 getenv_s(&homesize
, NULL
, 0, "HOME");
89 _dupenv_s(&home
,&size
,"USERPROFILE");
90 _putenv_s("HOME",home
);
93 GetModuleFileName(NULL
, path
, MAX_PATH
);
96 git_extract_argv0_path(path
);
97 g_prefix
= prefix
= setup_git_directory();
98 ret
= git_config(git_default_config
, NULL
);
102 _putenv_s("HOME","");/* clear home evironment to avoid affact third part software*/
108 static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR
*author
, char *pbuff
)
113 end
=strchr(pbuff
,'<');
118 author
->NameSize
= end
- pbuff
- 1;
121 end
= strchr(pbuff
, '>');
125 author
->Email
= pbuff
;
126 author
->EmailSize
= end
- pbuff
;
130 author
->Date
= atol(pbuff
);
131 end
= strchr(pbuff
, ' ');
136 author
->TimeZone
= atol(pbuff
);
141 int git_parse_commit(GIT_COMMIT
*commit
)
148 p
= (struct commit
*)commit
->m_pGitCommit
;
150 memcpy(commit
->m_hash
,p
->object
.sha1
,GIT_HASH_SIZE
);
152 commit
->m_Encode
= NULL
;
153 commit
->m_EncodeSize
= 0;
155 if(p
->buffer
== NULL
)
161 if( strncmp(pbuf
,"author",6) == 0)
163 ret
= git_parse_commit_author(&commit
->m_Author
,pbuf
+ 7);
167 if( strncmp(pbuf
, "committer",9) == 0)
169 ret
= git_parse_commit_author(&commit
->m_Committer
,pbuf
+ 10);
173 pbuf
= strchr(pbuf
,'\n');
177 while((*pbuf
) && (*pbuf
== '\n'))
180 if( strncmp(pbuf
, "encoding",8) == 0 )
183 commit
->m_Encode
=pbuf
;
184 end
= strchr(pbuf
,'\n');
185 commit
->m_EncodeSize
=end
-pbuf
;
188 while((*pbuf
) && (*pbuf
== '\n'))
191 commit
->m_Subject
=pbuf
;
192 end
= strchr(pbuf
,'\n');
194 commit
->m_SubjectSize
= strlen(pbuf
);
197 commit
->m_SubjectSize
= end
- pbuf
;
199 commit
->m_Body
= pbuf
;
200 commit
->m_BodySize
= strlen(pbuf
);
206 pbuf
= strchr(pbuf
,'\n');
213 int git_get_commit_from_hash(GIT_COMMIT
*commit
, GIT_HASH hash
)
219 memset(commit
,0,sizeof(GIT_COMMIT
));
221 commit
->m_pGitCommit
= p
= lookup_commit(hash
);
229 ret
= parse_commit(p
);
233 return git_parse_commit(commit
);
236 int git_get_commit_first_parent(GIT_COMMIT
*commit
,GIT_COMMIT_LIST
*list
)
238 struct commit
*p
= commit
->m_pGitCommit
;
243 *list
= (GIT_COMMIT_LIST
*)p
->parents
;
246 int git_get_commit_next_parent(GIT_COMMIT_LIST
*list
, GIT_HASH hash
)
248 struct commit_list
*l
= *(struct commit_list
**)list
;
249 if(list
== NULL
|| l
==NULL
)
253 memcpy(hash
, l
->item
->object
.sha1
, GIT_HASH_SIZE
);
255 *list
= (GIT_COMMIT_LIST
*)l
->next
;
261 int git_free_commit(GIT_COMMIT
*commit
)
263 struct commit
*p
= commit
->m_pGitCommit
;
266 free_commit_list(p
->parents
);
276 memset(commit
,0,sizeof(GIT_COMMIT
));
280 char **strtoargv(char *arg
, int *size
)
302 argv
=malloc(strlen(arg
)+1 + (count
+2)*sizeof(void*));
303 p
=(char*)(argv
+count
+2);
312 while(*arg
&& *arg
!= '"')
323 while(*arg
&& *arg
!=' ')
336 int git_open_log(GIT_LOG
* handle
, char * arg
)
338 struct rev_info
*p_Rev
;
343 struct setup_revision_opt opt
;
346 unsigned int obj_size
= get_max_object_index();
347 for(i
=0; i
<obj_size
; i
++)
349 struct object
*ob
= get_indexed_object(i
);
355 argv
= strtoargv(arg
,&argc
);
357 p_Rev
= malloc(sizeof(struct rev_info
));
358 memset(p_Rev
,0,sizeof(struct rev_info
));
363 init_revisions(p_Rev
, g_prefix
);
366 memset(&opt
, 0, sizeof(opt
));
369 cmd_log_init(argc
, argv
, g_prefix
,p_Rev
,&opt
);
371 p_Rev
->pPrivate
= argv
;
376 int git_get_log_firstcommit(GIT_LOG handle
)
378 return prepare_revision_walk(handle
);
381 int git_get_log_estimate_commit_count(GIT_LOG handle
)
383 struct rev_info
*p_Rev
;
384 p_Rev
=(struct rev_info
*)handle
;
386 return estimate_commit_count(p_Rev
, p_Rev
->commits
);
389 int git_get_log_nextcommit(GIT_LOG handle
, GIT_COMMIT
*commit
)
396 memset(commit
, 0, sizeof(GIT_COMMIT
));
398 commit
->m_pGitCommit
= get_revision(handle
);
399 if( commit
->m_pGitCommit
== NULL
)
402 ret
=git_parse_commit(commit
);
409 struct notes_tree
**display_notes_trees
;
410 int git_close_log(GIT_LOG handle
)
414 struct rev_info
*p_Rev
;
415 p_Rev
=(struct rev_info
*)handle
;
417 free(p_Rev
->pPrivate
);
421 free_notes(*display_notes_trees
);
422 display_notes_trees
= 0;
426 int git_open_diff(GIT_DIFF
*diff
, char * arg
)
428 struct rev_info
*p_Rev
;
434 argv
= strtoargv(arg
,&argc
);
436 p_Rev
= malloc(sizeof(struct rev_info
));
437 memset(p_Rev
,0,sizeof(struct rev_info
));
439 p_Rev
->pPrivate
= argv
;
440 *diff
= (GIT_DIFF
)p_Rev
;
442 init_revisions(p_Rev
, g_prefix
);
443 git_config(git_diff_basic_config
, NULL
); /* no "diff" UI options */
446 argc
= setup_revisions(argc
, argv
, p_Rev
, NULL
);
450 int git_close_diff(GIT_DIFF handle
)
452 git_diff_flush(handle
);
455 struct rev_info
*p_Rev
;
456 p_Rev
=(struct rev_info
*)handle
;
458 free(p_Rev
->pPrivate
);
463 int git_diff_flush(GIT_DIFF diff
)
465 struct diff_queue_struct
*q
= &diff_queued_diff
;
466 struct rev_info
*p_Rev
;
468 p_Rev
= (struct rev_info
*)diff
;
473 for (i
= 0; i
< q
->nr
; i
++)
474 diff_free_filepair(q
->queue
[i
]);
480 q
->nr
= q
->alloc
= 0;
483 if (p_Rev
->diffopt
.close_file
)
484 fclose(p_Rev
->diffopt
.close_file
);
486 free_diffstat_info(&p_Rev
->diffstat
);
489 int git_root_diff(GIT_DIFF diff
, GIT_HASH hash
,GIT_FILE
*file
, int *count
)
492 struct rev_info
*p_Rev
;
494 struct diff_queue_struct
*q
= &diff_queued_diff
;
496 p_Rev
= (struct rev_info
*)diff
;
498 ret
=diff_root_tree_sha1(hash
, "", &p_Rev
->diffopt
);
503 diffcore_std(&p_Rev
->diffopt
);
505 memset(&p_Rev
->diffstat
, 0, sizeof(struct diffstat_t
));
506 for (i
= 0; i
< q
->nr
; i
++) {
507 struct diff_filepair
*p
= q
->queue
[i
];
508 //if (check_pair_status(p))
509 diff_flush_stat(p
, &p_Rev
->diffopt
, &p_Rev
->diffstat
);
520 int git_diff(GIT_DIFF diff
, GIT_HASH hash1
, GIT_HASH hash2
, GIT_FILE
* file
, int *count
)
522 struct rev_info
*p_Rev
;
525 struct diff_queue_struct
*q
= &diff_queued_diff
;
527 p_Rev
= (struct rev_info
*)diff
;
529 ret
= diff_tree_sha1(hash1
,hash2
,"",&p_Rev
->diffopt
);
533 diffcore_std(&p_Rev
->diffopt
);
535 memset(&p_Rev
->diffstat
, 0, sizeof(struct diffstat_t
));
536 for (i
= 0; i
< q
->nr
; i
++) {
537 struct diff_filepair
*p
= q
->queue
[i
];
538 //if (check_pair_status(p))
539 diff_flush_stat(p
, &p_Rev
->diffopt
, &p_Rev
->diffstat
);
549 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
)
551 struct diff_queue_struct
*q
= &diff_queued_diff
;
552 struct rev_info
*p_Rev
;
553 p_Rev
= (struct rev_info
*)diff
;
555 q
= (struct diff_queue_struct
*)file
;
562 *newname
= q
->queue
[i
]->two
->path
;
565 *oldname
= q
->queue
[i
]->one
->path
;
568 *status
= q
->queue
[i
]->status
;
570 if(p_Rev
->diffstat
.files
)
573 for(j
=0;j
<p_Rev
->diffstat
.nr
;j
++)
575 if(strcmp(*newname
,p_Rev
->diffstat
.files
[j
]->name
)==0)
578 if( j
== p_Rev
->diffstat
.nr
)
586 *IsBin
= p_Rev
->diffstat
.files
[j
]->is_binary
;
588 *inc
= p_Rev
->diffstat
.files
[j
]->added
;
590 *dec
= p_Rev
->diffstat
.files
[j
]->deleted
;
601 int git_read_tree(GIT_HASH hash
,read_tree_fn_t fn
, void *context
)
605 reprepare_packed_git();
606 root
= parse_tree_indirect(hash
);
613 ret
= read_tree_recursive(root
,NULL
,NULL
,0,NULL
,fn
,context
);
618 int git_add_exclude(const char *string
, const char *base
,
619 int baselen
, struct exclude_list
*which
)
621 add_exclude(string
, base
, baselen
, which
);
625 int git_create_exclude_list(EXCLUDE_LIST
*which
)
627 *which
= malloc(sizeof(struct exclude_list
));
628 memset(*which
,0,sizeof(struct exclude_list
));
632 int git_free_exclude_list(EXCLUDE_LIST which
)
635 struct exclude_list
*p
= (struct exclude_list
*) which
;
637 for(i
=0; i
<p
->nr
;i
++)
639 free(p
->excludes
[i
]);
645 int git_check_excluded_1(const char *pathname
,
646 int pathlen
, const char *basename
, int *dtype
,
649 return excluded_from_list(pathname
, pathlen
, basename
,dtype
,el
);
652 int git_get_notes(GIT_HASH hash
, char **p_note
)
657 format_display_notes(hash
, &sb
, "utf-8", 0);
658 *p_note
= strbuf_detach(&sb
,&size
);
665 int (*fn
)(int, const char **, const char *);
669 #define RUN_SETUP (1<<0)
670 #define USE_PAGER (1<<1)
672 * require working tree to be present -- anything uses this needs
673 * RUN_SETUP for reading from the configuration file.
675 #define NEED_WORK_TREE (1<<2)
677 const char git_usage_string
[] =
678 "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
679 " [-p|--paginate|--no-pager] [--no-replace-objects]\n"
680 " [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
681 " [-c name=value] [--help]\n"
684 const char git_more_info_string
[] =
685 "See 'git help COMMAND' for more information on a specific command.";
687 /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
688 int check_pager_config(const char *cmd
)
694 int git_run_cmd(char *cmd
, char *arg
)
701 static struct cmd_struct commands
[] = {
702 { "add", cmd_add
, RUN_SETUP
| NEED_WORK_TREE
},
703 { "stage", cmd_add
, RUN_SETUP
| NEED_WORK_TREE
},
704 { "annotate", cmd_annotate
, RUN_SETUP
},
705 { "apply", cmd_apply
},
706 { "archive", cmd_archive
},
707 { "bisect--helper", cmd_bisect__helper
, RUN_SETUP
| NEED_WORK_TREE
},
708 { "blame", cmd_blame
, RUN_SETUP
},
709 { "branch", cmd_branch
, RUN_SETUP
},
710 { "bundle", cmd_bundle
},
711 { "cat-file", cmd_cat_file
, RUN_SETUP
},
712 { "checkout", cmd_checkout
, RUN_SETUP
| NEED_WORK_TREE
},
713 { "checkout-index", cmd_checkout_index
,
714 RUN_SETUP
| NEED_WORK_TREE
},
715 { "check-ref-format", cmd_check_ref_format
},
716 { "check-attr", cmd_check_attr
, RUN_SETUP
},
717 { "cherry", cmd_cherry
, RUN_SETUP
},
718 { "cherry-pick", cmd_cherry_pick
, RUN_SETUP
| NEED_WORK_TREE
},
719 { "clone", cmd_clone
},
720 { "clean", cmd_clean
, RUN_SETUP
| NEED_WORK_TREE
},
721 { "commit", cmd_commit
, RUN_SETUP
| NEED_WORK_TREE
},
722 { "commit-tree", cmd_commit_tree
, RUN_SETUP
},
723 { "config", cmd_config
},
724 { "count-objects", cmd_count_objects
, RUN_SETUP
},
725 { "describe", cmd_describe
, RUN_SETUP
},
726 { "diff", cmd_diff
},
727 { "diff-files", cmd_diff_files
, RUN_SETUP
| NEED_WORK_TREE
},
728 { "diff-index", cmd_diff_index
, RUN_SETUP
},
729 { "diff-tree", cmd_diff_tree
, RUN_SETUP
},
730 { "fast-export", cmd_fast_export
, RUN_SETUP
},
731 { "fetch", cmd_fetch
, RUN_SETUP
},
732 { "fetch-pack", cmd_fetch_pack
, RUN_SETUP
},
733 { "fmt-merge-msg", cmd_fmt_merge_msg
, RUN_SETUP
},
734 { "for-each-ref", cmd_for_each_ref
, RUN_SETUP
},
735 { "format-patch", cmd_format_patch
, RUN_SETUP
},
736 { "fsck", cmd_fsck
, RUN_SETUP
},
737 { "fsck-objects", cmd_fsck
, RUN_SETUP
},
738 { "gc", cmd_gc
, RUN_SETUP
},
739 { "get-tar-commit-id", cmd_get_tar_commit_id
},
740 { "grep", cmd_grep
},
741 { "hash-object", cmd_hash_object
},
742 { "help", cmd_help
},
743 { "index-pack", cmd_index_pack
},
744 { "init", cmd_init_db
},
745 { "init-db", cmd_init_db
},
746 { "log", cmd_log
, RUN_SETUP
},
747 { "ls-files", cmd_ls_files
, RUN_SETUP
},
748 { "ls-tree", cmd_ls_tree
, RUN_SETUP
},
749 { "ls-remote", cmd_ls_remote
},
750 { "mailinfo", cmd_mailinfo
},
751 { "mailsplit", cmd_mailsplit
},
752 { "merge", cmd_merge
, RUN_SETUP
| NEED_WORK_TREE
},
753 { "merge-base", cmd_merge_base
, RUN_SETUP
},
754 { "merge-file", cmd_merge_file
},
755 { "merge-index", cmd_merge_index
, RUN_SETUP
},
756 { "merge-ours", cmd_merge_ours
, RUN_SETUP
},
757 { "merge-recursive", cmd_merge_recursive
, RUN_SETUP
| NEED_WORK_TREE
},
758 { "merge-recursive-ours", cmd_merge_recursive
, RUN_SETUP
| NEED_WORK_TREE
},
759 { "merge-recursive-theirs", cmd_merge_recursive
, RUN_SETUP
| NEED_WORK_TREE
},
760 { "merge-subtree", cmd_merge_recursive
, RUN_SETUP
| NEED_WORK_TREE
},
761 { "merge-tree", cmd_merge_tree
, RUN_SETUP
},
762 { "mktag", cmd_mktag
, RUN_SETUP
},
763 { "mktree", cmd_mktree
, RUN_SETUP
},
764 { "mv", cmd_mv
, RUN_SETUP
| NEED_WORK_TREE
},
765 { "name-rev", cmd_name_rev
, RUN_SETUP
},
766 { "notes", cmd_notes
, RUN_SETUP
},
767 { "pack-objects", cmd_pack_objects
, RUN_SETUP
},
768 { "pack-redundant", cmd_pack_redundant
, RUN_SETUP
},
769 { "patch-id", cmd_patch_id
},
770 { "peek-remote", cmd_ls_remote
},
771 { "pickaxe", cmd_blame
, RUN_SETUP
},
772 { "prune", cmd_prune
, RUN_SETUP
},
773 { "prune-packed", cmd_prune_packed
, RUN_SETUP
},
774 { "push", cmd_push
, RUN_SETUP
},
775 { "read-tree", cmd_read_tree
, RUN_SETUP
},
776 { "receive-pack", cmd_receive_pack
},
777 { "reflog", cmd_reflog
, RUN_SETUP
},
778 { "remote", cmd_remote
, RUN_SETUP
},
779 { "replace", cmd_replace
, RUN_SETUP
},
780 { "repo-config", cmd_config
},
781 { "rerere", cmd_rerere
, RUN_SETUP
},
782 { "reset", cmd_reset
, RUN_SETUP
},
783 { "rev-list", cmd_rev_list
, RUN_SETUP
},
784 { "rev-parse", cmd_rev_parse
},
785 { "revert", cmd_revert
, RUN_SETUP
| NEED_WORK_TREE
},
786 { "rm", cmd_rm
, RUN_SETUP
},
787 { "send-pack", cmd_send_pack
, RUN_SETUP
},
788 { "shortlog", cmd_shortlog
, USE_PAGER
},
789 { "show-branch", cmd_show_branch
, RUN_SETUP
},
790 { "show", cmd_show
, RUN_SETUP
},
791 { "status", cmd_status
, RUN_SETUP
| NEED_WORK_TREE
},
792 { "stripspace", cmd_stripspace
},
793 { "symbolic-ref", cmd_symbolic_ref
, RUN_SETUP
},
794 { "tag", cmd_tag
, RUN_SETUP
},
795 { "tar-tree", cmd_tar_tree
},
796 { "unpack-file", cmd_unpack_file
, RUN_SETUP
},
797 { "unpack-objects", cmd_unpack_objects
, RUN_SETUP
},
798 { "update-index", cmd_update_index
, RUN_SETUP
},
799 { "update-ref", cmd_update_ref
, RUN_SETUP
},
800 { "update-server-info", cmd_update_server_info
, RUN_SETUP
},
801 { "upload-archive", cmd_upload_archive
},
803 { "verify-tag", cmd_verify_tag
, RUN_SETUP
},
804 { "version", cmd_version
},
805 { "whatchanged", cmd_whatchanged
, RUN_SETUP
},
806 { "write-tree", cmd_write_tree
, RUN_SETUP
},
807 { "verify-pack", cmd_verify_pack
},
808 { "show-ref", cmd_show_ref
, RUN_SETUP
},
809 { "pack-refs", cmd_pack_refs
, RUN_SETUP
},
814 for(i
=0;i
< sizeof(commands
) / sizeof(struct cmd_struct
);i
++)
816 if(strcmp(cmd
,commands
[i
].cmd
)==0)
820 argv
= strtoargv(arg
,&argc
);
822 ret
= commands
[i
].fn(argc
, argv
, NULL
);