git 源碼學習(init-db) 提交版本號 083c516331
寫在前面的廢話:
學完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.git3 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