1. 程式人生 > >git 源碼學習(init-db) 提交版本號 083c516331

git 源碼學習(init-db) 提交版本號 083c516331

ani 修改 函數 新的 define 版本號 html_ clone zlib

寫在前面的廢話:

學完git之後,還是感覺雲裏霧裏的,於是乎,就想到了通過學習git源碼,來加深git的熟練度,同時學習一下c語言編程。

git源碼學習,逐步分析

這篇帖子是逐步分析git源碼的,將git的源碼按照邏輯塊剝離出來,形成一個可執行程序,以便進一步了解git。當然分析的git源碼是從git第一次提交開始的。最新的git源碼,做為菜鳥的我是不可能看懂的,這輩子都不可能看懂的。接下來進入正題。

1.準備工作

1.1 git clone git源碼:

在git命令行中鍵入如下代碼

1 // 二選一,即可
2 git clone https://github.com/git/git.git
3 4 git clone [email protected]:/git/git.git

git源碼下載完成之後,切換到第一次提交的源碼,步驟如下:

切換到git源碼所在的目錄下,命令行中鍵入如下代碼

1 cd /your_local_directory/git
2 
3 git log --reverse    // 打印順序從最早到現在
4  
5 git reset --hard 083c516331   //  git 源碼的第一次提交號

如果想要返回最新的版本,可以使用如下命令

git reflog         // 查看操作歷史記錄,其中git clone 前面的commit號就是最新的git源碼所在地
git reset --hard <commit> // 執行git log,查看已經是最新的源碼了

2.修改Makefile,生成可執行文件

將LIBS=-lssl修改為LIBS=-lcrypto -lz

原版的Makefile不能make成功,愈發之後即可通過。(此處不知原因,有待進一步查明,望哪位大佬指出,謝謝)

如果編譯提示找不<openssl/sha.h>,安裝libssl-dev即可

如果編譯提示找不<zlib.h>,安裝zlib即可

完成修改之後,make基本可以成功。

3.分析init-db.c源碼

<cache.h>中包含一些標準頭文件、宏和自定義的函數

第一個邏輯塊是生成一個.dircache文件,相當於git現在的.git文件,剝離出來代碼如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/stat.h>
 4 
 5 #define DB_ENVIRONMENT "SHA1_FILE_DIRECTOY"
 6 
 7 int main(int argc, char **argv)
 8 {
 9     char *sha1_dir = getenv(DB_ENVIRONMENT), *path;
10     int len, i, fd;
11 
12         /* https://www.gnu.org/software/libc/manual/html_node/Creating-Directories.html 
13          * mkdir() 是gnu函數,包含在<sys/stat.h>頭文件中,詳細信息見鏈接
14          */
15     if (mkdir(".dircache", 0700) < 0) {
16         perror("unable to create .dircache");
17         exit(1);
18     }
19 
20     return 0;
21 }

第二個邏輯塊是獲取環境變量,並檢查該文件是不是一個directory。

 1  #include <stdio.h>
 2  #include <stdlib.h>
 3  #include <sys/stat.h>
 4  #include <fcntl.h>
 5  
 6  #define DB_ENVIRONMENT "SHA1_FILE_DIRECTOY"
 7  
 8  int main(int argc, char **argv)
 9  {
10      char *sha1_dir = getenv(DB_ENVIRONMENT), *path;
11      int len, i, fd;
12  
13      if (mkdir(".dircache", 0700) < 0) {
14          perror("unable to create .dircache");
15          exit(1);
16      }
17          /* http://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html
18           * stat()函數詳情 
19           * https://www.gnu.org/software/libc/manual/html_node/Attribute-Meanings.html
20           * struct stat 結構體詳情
21           */
22      sha1_dir = getenv(DB_ENVIRONMENT);
23      if (sha1_dir) {
24          struct stat st;
25          if (!stat(sha1_dir, &st) < 0 && S_ISDIR(st.st_mode))
26              return 0;
27          fprintf(stderr, "DB_ENVIRONMENT set to bad directory %s: ", sha1_dir);
28      }
29  
30      return 0;
31   }

第三個邏輯塊是在.dircache目錄下生成一個objects文件,此文件用來保存sha1值,即commit號。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 #include <errno.h>
 7 
 8 #define DB_ENVIRONMENT "SHA1_FILE_DIRECTOY"
 9 #define DEFAULT_DB_ENVIRONMENT ".dircache/objects"
10 
11 int main(int argc, char **argv)
12 {
13     char *sha1_dir = getenv(DB_ENVIRONMENT), *path;
14     int len, i, fd;
15 
16     /* printf("%s\n", sha1_dir); */
17 
18     if (mkdir(".dircache", 0700) < 0) {
19         perror("unable to create .dircache");
20         exit(1);
21     }
22 
23     sha1_dir = getenv(DB_ENVIRONMENT);
24     if (sha1_dir) {
25         struct stat st;
26         if (!stat(sha1_dir, &st) < 0 && S_ISDIR(st.st_mode))
27             return 0;
28         fprintf(stderr, "DB_ENVIRONMENT set to bad directory %s: ", sha1_dir);
29     }
30 
31     sha1_dir = DEFAULT_DB_ENVIRONMENT;
32     fprintf(stderr, "defaulting to private storage area\n");
33     len = strlen(sha1_dir);
34     if (mkdir(sha1_dir, 0700) < 0) {
35         if (errno != EEXIST) {
36             perror(sha1_dir);
37             exit(1);
38         }
39     }
40 
41     return 0;
42 }

最後一個邏輯塊是在objects目錄下生成256個文件,文件名稱是從00-ff。這些文件用來保存sha1值,即commit號,比如commit號為083c516331,會保存在08目錄中內容為3c516331

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 #include <errno.h>
 7 
 8 #define DB_ENVIRONMENT "SHA1_FILE_DIRECTOY"
 9 #define DEFAULT_DB_ENVIRONMENT ".dircache/objects"
10 
11 int main(int argc, char **argv)
12 {
13     char *sha1_dir = getenv(DB_ENVIRONMENT), *path;
14     int len, i, fd;
15 
16     if (mkdir(".dircache", 0700) < 0) {
17         perror("unable to create .dircache");
18         exit(1);
19     }
20 
21     sha1_dir = getenv(DB_ENVIRONMENT);
22     if (sha1_dir) {
23         struct stat st;
24         if (!stat(sha1_dir, &st) < 0 && S_ISDIR(st.st_mode))
25             return 0;
26         fprintf(stderr, "DB_ENVIRONMENT set to bad directory %s: ", sha1_dir);
27     }
28 
29     sha1_dir = DEFAULT_DB_ENVIRONMENT;
30     fprintf(stderr, "defaulting to private storage area\n");
31     len = strlen(sha1_dir);
32     if (mkdir(sha1_dir, 0700) < 0) {
33         if (errno != EEXIST) {
34             perror(sha1_dir);
35             exit(1);
36         }
37     }
38 
39     path = malloc(len + 40);
40     memcpy(path, sha1_dir, len);
41     for (i = 0; i < 256; i++) {
42         sprintf(path+len, "/%02x", i);
43         if (mkdir(path, 0700) < 0) {
44             if (errno != EEXIST) {
45                 perror(path);
46                 exit(1);
47             }
48         }
49     }
50     free(path);
51 
52     return 0;
53 }

至此init-db.c分析完畢,謝謝閱讀,如有不足之處,歡迎指出郵箱[email protected]

git 源碼學習(init-db) 提交版本號 083c516331