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.git 3 4 git clone git@github.com:/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分析完毕,谢谢阅读,如有不足之处,欢迎指出邮箱brucecontact@163.com
上一篇: Python学习01