OSDN Git Service

merge original branch.
[tortoisegit/TortoiseGitJp.git] / ext / gitdll / gitdll.c
index af92ef0..77607b1 100644 (file)
@@ -2,7 +2,16 @@
 //\r
 \r
 #include "stdafx.h"\r
+#include "git-compat-util.h"\r
+#include "msvc.h"\r
 #include "gitdll.h"\r
+#include "cache.h"\r
+#include "commit.h"\r
+#include "diff.h"\r
+#include "revision.h"\r
+#include "diffcore.h"\r
+const char git_version_string[] = GIT_VERSION;\r
+\r
 \r
 #if 0\r
 \r
@@ -25,6 +34,7 @@ Cgitdll::Cgitdll()
 \r
 #define MAX_ERROR_STR_SIZE 512\r
 char g_last_error[MAX_ERROR_STR_SIZE]={0};\r
+void * g_prefix;\r
 \r
 char * get_git_last_error()\r
 {\r
@@ -42,7 +52,524 @@ void dll_entry()
        set_die_routine(die_dll);\r
 }\r
 \r
-int git_get_sha1(const char *name, unsigned char *sha1)\r
+int git_get_sha1(const char *name, GIT_HASH sha1)\r
 {\r
        return get_sha1(name,sha1);\r
+}\r
+\r
+static int convert_slash(char * path)\r
+{\r
+       while(*path)\r
+       {\r
+               if(*path == '\\' )\r
+                       *path = '/';\r
+               path++;\r
+       }\r
+}\r
+\r
+int git_init()\r
+{\r
+       char *home;\r
+       char path[MAX_PATH+1];\r
+       char *prefix;\r
+       size_t homesize,size,httpsize;\r
+\r
+       _fmode = _O_BINARY; \r
+       _setmode(_fileno(stdin), _O_BINARY); \r
+       _setmode(_fileno(stdout), _O_BINARY); \r
+       _setmode(_fileno(stderr), _O_BINARY); \r
+\r
+       // set HOME if not set already\r
+       getenv_s(&homesize, NULL, 0, "HOME");\r
+       if (!homesize)\r
+       {\r
+               _dupenv_s(&home,&size,"USERPROFILE"); \r
+               _putenv_s("HOME",home);\r
+               free(home);\r
+       }\r
+       GetModuleFileName(NULL, path, MAX_PATH);\r
+       convert_slash(path);\r
+\r
+       git_extract_argv0_path(path);\r
+       g_prefix = prefix = setup_git_directory();\r
+       return git_config(git_default_config, NULL);\r
+}\r
+\r
+static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR *author, char *pbuff)\r
+{\r
+       char *end;\r
+\r
+       author->Name=pbuff;\r
+       end=strchr(pbuff,'<');\r
+       if( end == 0)\r
+       {\r
+               return -1;\r
+       }\r
+       author->NameSize = end - pbuff - 1;\r
+\r
+       pbuff = end +1;\r
+       end = strchr(pbuff, '>');\r
+       if( end == 0)\r
+               return -1;\r
+\r
+       author->Email = pbuff ;\r
+       author->EmailSize = end - pbuff;\r
+\r
+       pbuff = end + 2;\r
+\r
+       author->Date = atol(pbuff);\r
+       end =  strchr(pbuff, ' ');\r
+       if( end == 0 )\r
+               return -1;\r
+\r
+       pbuff=end;\r
+       author->TimeZone = atol(pbuff);\r
+\r
+       return 0;\r
+}\r
+\r
+int git_parse_commit(GIT_COMMIT *commit)\r
+{\r
+       int ret = 0;\r
+       char *pbuf;\r
+       char *end;\r
+       struct commit *p;\r
+\r
+       p= (struct commit *)commit->m_pGitCommit;\r
+\r
+       memcpy(commit->m_hash,p->object.sha1,GIT_HASH_SIZE);\r
+\r
+       commit->m_Encode = NULL;\r
+       commit->m_EncodeSize = 0;\r
+\r
+       if(p->buffer == NULL)\r
+               return -1;\r
+\r
+       pbuf = p->buffer;\r
+       while(pbuf)\r
+       {\r
+               if( strncmp(pbuf,"author",6) == 0)\r
+               {\r
+                       ret = git_parse_commit_author(&commit->m_Author,pbuf + 7);\r
+                       if(ret)\r
+                               return ret;\r
+               }\r
+               if( strncmp(pbuf, "committer",9) == 0)\r
+               {\r
+                       ret =  git_parse_commit_author(&commit->m_Committer,pbuf + 10);\r
+                       if(ret)\r
+                               return ret;\r
+\r
+                       pbuf = strchr(pbuf,'\n');\r
+                       if(pbuf == NULL)\r
+                               return -1;\r
+\r
+                       while((*pbuf) && (*pbuf == '\n'))\r
+                               pbuf ++;\r
+\r
+                       if( strncmp(pbuf, "encoding",8) == 0 )\r
+                       {\r
+                               pbuf += 9;\r
+                               commit->m_Encode=pbuf;\r
+                               end = strchr(pbuf,'\n');\r
+                               commit->m_EncodeSize=end -pbuf;\r
+\r
+                               pbuf = end +1;\r
+                               while((*pbuf) && (*pbuf == '\n'))\r
+                                       pbuf ++;\r
+                       }\r
+                       commit->m_Subject=pbuf;\r
+                       end = strchr(pbuf,'\n');\r
+                       if( end == 0)\r
+                               commit->m_SubjectSize = strlen(pbuf);\r
+                       else\r
+                       {\r
+                               commit->m_SubjectSize = end - pbuf;\r
+                               pbuf = end +1;\r
+                               commit->m_Body = pbuf;\r
+                               commit->m_BodySize = strlen(pbuf);\r
+                               return 0;\r
+                       }\r
+\r
+               }\r
+\r
+               pbuf = strchr(pbuf,'\n');\r
+               if(pbuf)\r
+                       pbuf ++;\r
+       }\r
+\r
+}\r
+\r
+int git_get_commit_from_hash(GIT_COMMIT *commit, GIT_HASH hash)\r
+{\r
+       int ret = 0;\r
+       \r
+       struct commit *p;\r
+       \r
+       memset(commit,0,sizeof(GIT_COMMIT));\r
+\r
+       commit->m_pGitCommit = p = lookup_commit(hash);\r
+\r
+       if(commit == NULL)\r
+               return -1;\r
+       \r
+       if(p == NULL)\r
+               return -1;\r
+       \r
+       ret = parse_commit(p);\r
+       if( ret )\r
+               return ret;\r
+\r
+       return git_parse_commit(commit);\r
+}\r
+\r
+int git_get_commit_first_parent(GIT_COMMIT *commit,GIT_COMMIT_LIST *list)\r
+{\r
+       struct commit *p = commit->m_pGitCommit;\r
+\r
+       if(list == NULL)\r
+               return -1;\r
+       \r
+       *list = (GIT_COMMIT_LIST*)p->parents;\r
+       return 0;\r
+}\r
+int git_get_commit_next_parent(GIT_COMMIT_LIST *list, GIT_HASH hash)\r
+{\r
+       struct commit_list *l = *(struct commit_list **)list;\r
+       if(list == NULL || l==NULL)\r
+               return -1;\r
+\r
+       if(hash)\r
+               memcpy(hash, l->item->object.sha1, GIT_HASH_SIZE);\r
+\r
+       *list = (GIT_COMMIT_LIST *)l->next;\r
+       return 0;\r
+\r
+}\r
+\r
+\r
+int git_free_commit(GIT_COMMIT *commit)\r
+{\r
+       struct commit *p = commit->m_pGitCommit;\r
+\r
+       if( p->parents)\r
+               free_commit_list(p->parents);   \r
+\r
+       if( p->buffer )\r
+       {\r
+               free(p->buffer);\r
+               p->buffer=NULL;\r
+               p->object.parsed=0;\r
+               p->parents=0;\r
+               p->tree=0;\r
+       }\r
+       memset(commit,0,sizeof(GIT_COMMIT));\r
+       return 0;\r
+}\r
+\r
+char **strtoargv(char *arg, int *size)\r
+{\r
+       int count=0;\r
+       char *p=arg;\r
+       char **argv;\r
+       \r
+       int i=0;\r
+       while(*p)\r
+       {\r
+               if(*p == '\\')\r
+                       *p='/';\r
+               p++;\r
+       }\r
+       p=arg;\r
+\r
+       while(*p)\r
+       {\r
+               if(*p == ' ')\r
+                       count ++;\r
+               p++;\r
+       }\r
+       \r
+       argv=malloc(strlen(arg)+1 + (count +2)*sizeof(void*));\r
+       p=(char*)(argv+count+2);\r
+\r
+       while(*arg)\r
+       {\r
+               if(*arg == '"')\r
+               {\r
+                       argv[i] = p;\r
+                       arg++;\r
+                       *p=*arg;\r
+                       while(*arg && *arg!= '"')\r
+                               *p++=*arg++;\r
+                       *p++=0;\r
+                       arg++;\r
+                       i++;\r
+                       if(*arg == 0)\r
+                               break;\r
+               }\r
+               if(*arg != ' ')\r
+               {\r
+                       argv[i]=p;\r
+                       while(*arg && *arg !=' ')\r
+                               *p++ = *arg++;\r
+                       i++;\r
+                       *p++=0;\r
+               }\r
+               arg++;\r
+       }\r
+       argv[i]=NULL;\r
+       *size = i;\r
+       return argv;\r
+}\r
+int git_open_log(GIT_LOG * handle, char * arg)\r
+{\r
+       struct rev_info *p_Rev;\r
+       int size;\r
+       char ** argv=0;\r
+       int argc=0;\r
+       int i=0;\r
+\r
+       /* clear flags */\r
+       unsigned int obj_size = get_max_object_index();\r
+       for(i =0; i<obj_size; i++)\r
+       {\r
+               struct object *ob= get_indexed_object(i);\r
+               if(ob)\r
+                       ob->flags=0;\r
+       }\r
+\r
+       if(arg != NULL)\r
+               argv = strtoargv(arg,&argc);\r
+\r
+       p_Rev = malloc(sizeof(struct rev_info));\r
+       memset(p_Rev,0,sizeof(struct rev_info));\r
+\r
+       if(p_Rev == NULL)\r
+               return -1;\r
+\r
+       init_revisions(p_Rev, g_prefix);\r
+       p_Rev->diff = 1;\r
+               \r
+       cmd_log_init(argc, argv, g_prefix,p_Rev);\r
+\r
+       p_Rev->pPrivate = argv;\r
+       *handle = p_Rev;\r
+       return 0;\r
+\r
+}\r
+int git_get_log_firstcommit(GIT_LOG handle)\r
+{\r
+       return prepare_revision_walk(handle);\r
+}\r
+\r
+int git_get_log_estimate_commit_count(GIT_LOG handle)\r
+{\r
+       struct rev_info *p_Rev;\r
+       p_Rev=(struct rev_info *)handle;\r
+\r
+       return estimate_commit_count(p_Rev, p_Rev->commits);\r
+}\r
+\r
+int git_get_log_nextcommit(GIT_LOG handle, GIT_COMMIT *commit)\r
+{\r
+       int ret =0;\r
+\r
+       commit->m_pGitCommit = get_revision(handle);\r
+       if( commit->m_pGitCommit == NULL)\r
+               return -2;\r
+       \r
+       ret=git_parse_commit(commit);\r
+       if(ret)\r
+               return ret;\r
+\r
+       return 0;\r
+}\r
+\r
+int git_close_log(GIT_LOG handle)\r
+{\r
+       if(handle)\r
+       {\r
+               struct rev_info *p_Rev;\r
+               p_Rev=(struct rev_info *)handle;\r
+               if(p_Rev->pPrivate)\r
+                       free(p_Rev->pPrivate);\r
+               free(handle);\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+int git_open_diff(GIT_DIFF *diff, char * arg)\r
+{\r
+       struct rev_info *p_Rev;\r
+       int size;\r
+       char ** argv=0;\r
+       int argc=0;\r
+               \r
+       if(arg != NULL)\r
+               argv = strtoargv(arg,&argc);\r
+\r
+       p_Rev = malloc(sizeof(struct rev_info));\r
+       memset(p_Rev,0,sizeof(struct rev_info));\r
+\r
+       p_Rev->pPrivate = argv;\r
+       *diff = (GIT_DIFF)p_Rev;\r
+\r
+       init_revisions(p_Rev, g_prefix);\r
+       git_config(git_diff_basic_config, NULL); /* no "diff" UI options */\r
+       p_Rev->abbrev = 0;\r
+       p_Rev->diff = 1;\r
+       argc = setup_revisions(argc, argv, p_Rev, NULL);\r
+\r
+       return 0;\r
+}\r
+int git_close_diff(GIT_DIFF handle)\r
+{\r
+       git_diff_flush(handle);\r
+       if(handle)\r
+       {\r
+               struct rev_info *p_Rev;\r
+               p_Rev=(struct rev_info *)handle;\r
+               if(p_Rev->pPrivate)\r
+                       free(p_Rev->pPrivate);\r
+               free(handle);\r
+       }\r
+       return 0;\r
+}\r
+int git_diff_flush(GIT_DIFF diff)\r
+{\r
+       struct diff_queue_struct *q = &diff_queued_diff;\r
+       struct rev_info *p_Rev;\r
+       int i;\r
+       p_Rev = (struct rev_info *)diff;\r
+       \r
+       if(q->nr == 0)\r
+               return 0;\r
+\r
+       for (i = 0; i < q->nr; i++)\r
+               diff_free_filepair(q->queue[i]);\r
+\r
+       if(q->queue)\r
+       {\r
+               free(q->queue);\r
+               q->queue = NULL;\r
+               q->nr = q->alloc = 0;\r
+       }\r
+\r
+       if (p_Rev->diffopt.close_file)\r
+               fclose(p_Rev->diffopt.close_file);\r
+\r
+       free_diffstat_info(&p_Rev->diffstat);\r
+}\r
+\r
+int git_root_diff(GIT_DIFF diff, GIT_HASH hash,GIT_FILE *file, int *count)\r
+{\r
+       int ret;\r
+       struct rev_info *p_Rev;\r
+       int i;\r
+       struct diff_queue_struct *q = &diff_queued_diff;\r
+\r
+       p_Rev = (struct rev_info *)diff;\r
+\r
+       ret=diff_root_tree_sha1(hash, "", &p_Rev->diffopt);\r
+\r
+       if(ret)\r
+               return ret;\r
+\r
+       diffcore_std(&p_Rev->diffopt);\r
+\r
+       memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));\r
+       for (i = 0; i < q->nr; i++) {\r
+               struct diff_filepair *p = q->queue[i];\r
+               //if (check_pair_status(p))\r
+               diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);\r
+       }\r
+\r
+       if(file)\r
+               *file = q;\r
+       if(count)\r
+               *count = q->nr;\r
+\r
+       return 0;\r
+}\r
+\r
+int git_diff(GIT_DIFF diff, GIT_HASH hash1, GIT_HASH hash2, GIT_FILE * file, int *count)\r
+{\r
+       struct rev_info *p_Rev;\r
+       int ret;\r
+       int i;\r
+       struct diff_queue_struct *q = &diff_queued_diff;\r
+       \r
+       p_Rev = (struct rev_info *)diff;\r
+\r
+       ret = diff_tree_sha1(hash1,hash2,"",&p_Rev->diffopt);\r
+       if( ret )\r
+               return ret;\r
+       \r
+       diffcore_std(&p_Rev->diffopt);\r
+\r
+       memset(&p_Rev->diffstat, 0, sizeof(struct diffstat_t));\r
+       for (i = 0; i < q->nr; i++) {\r
+               struct diff_filepair *p = q->queue[i];\r
+               //if (check_pair_status(p))\r
+               diff_flush_stat(p, &p_Rev->diffopt, &p_Rev->diffstat);\r
+       }\r
+\r
+       if(file)\r
+               *file = q;\r
+       if(count)\r
+               *count = q->nr;\r
+       return 0;\r
+}\r
+\r
+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
+{\r
+       struct diff_queue_struct *q = &diff_queued_diff;\r
+       struct rev_info *p_Rev;\r
+       p_Rev = (struct rev_info *)diff;\r
+       \r
+       q = (struct diff_queue_struct *)file;\r
+       if(file == 0)\r
+               return -1;\r
+       if(i>=q->nr)\r
+               return -1;\r
+\r
+       if(newname)\r
+               *newname = q->queue[i]->two->path;\r
+\r
+       if(oldname)\r
+               *oldname = q->queue[i]->one->path;\r
+\r
+       if(status)\r
+               *status = q->queue[i]->status;\r
+\r
+       if(p_Rev->diffstat.files)\r
+       {\r
+               int j;\r
+               for(j=0;j<p_Rev->diffstat.nr;j++)\r
+               {\r
+                       if(strcmp(*newname,p_Rev->diffstat.files[j]->name)==0)\r
+                               break;\r
+               }\r
+               if( j== p_Rev->diffstat.nr)\r
+               {\r
+                       *IsBin=1;\r
+                       *inc=0;\r
+                       *dec=0;\r
+                       return 0;\r
+               }\r
+               if(IsBin)\r
+                       *IsBin = p_Rev->diffstat.files[j]->is_binary;\r
+               if(inc)\r
+                       *inc = p_Rev->diffstat.files[j]->added;\r
+               if(dec)\r
+                       *dec = p_Rev->diffstat.files[j]->deleted;\r
+       }else\r
+       {\r
+               *IsBin=1;\r
+               *inc=0;\r
+               *dec=0;\r
+       }\r
+\r
+       return 0;\r
 }
\ No newline at end of file