git 源码解析(三)write_tree

write_tree作用将读取的active_cache的多个文件归并到一个类型为tree的sha1文件中

update_catch功能是保存每个源数据文件信息到sha1文件,但各个文件信息是独立的,write_tree的作用是将一次update-catch的多个文件归并到一个类型为tree的sha1文件中 

int main(int argc, char **argv)
{
    entries = read_cache();
    buffer = malloc(size);
    offset = ORIG_OFFSET; // 40
    // buffer: "[..40..]%o %s\0sha1%o %s\0sha1...%o %s\0sha1"
    for (i = 0; i < entries; i++) 
        struct cache_entry *ce = active_cache[i];
        offset += sprintf(buffer + offset, "%o %s", ce->st_mode, ce->name);
        buffer[offset++] = 0;
        memcpy(buffer + offset, ce->sha1, 20);
        offset += 20;
    // buffer: "[..x..]%lu\0%o %s\0sha1%o %s\0sha1...%o %s\0sha1"
    i = prepend_integer(buffer, offset - ORIG_OFFSET, ORIG_OFFSET); 
        i -= 5;
        // buffer: "[..x-5..]tree %lu\0%o %s\0sha1%o %s\0sha1...%o %s\0sha1"
        memcpy(buffer+i, "tree ", 5); 
        buffer += i; 
        offset -= i; 
        // buffer: "tree %lu\0%o %s\0sha1%o %s\0sha1...%o %s\0sha1"
        // %lu: size of "%o %s\0sha1%o %s\0sha1...%o %s\0sha1"
        // offset: size of buffer
        write_sha1_file(buffer, offset);
            stream.next_in = buffer;
            stream.avail_in = offset;
            stream.next_out = compressed;
            stream.avail_out = size;
            while (deflate(&stream, Z_FINISH) == Z_OK);
            size = stream.total_out;
            SHA1_Init(&c);
            SHA1_Update(&c, compressed, size);
            SHA1_Final(sha1, &c);
            write_sha1_buffer(sha1, compressed, size);
                char *filename = sha1_file_name(sha1);
                fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
                write(fd, compressed, size);
                close(fd);
}

 

1. entries = read_cache(); # 从.dircache/index文件读取已保存的catch_entry信息,载入到内存中

函数详情见https://blog.csdn.net/chenwh_cn/article/details/84901286

 

2. buffer信息格式:tree %lu\0%o %s\0sha1%o %s\0sha1.....%o %s\0sha1

%lu # "%o %s\0sha1%o %s\0sha1.....%o %s\0sha1" 字节长度

%o # catch_entry中保存的源数据文件st_mode信息

%s # catch_entry中保存的源数据文件name信息

 

3. write_sha1_file(buffer, offset); # 

int write_sha1_file(char *buf, unsigned len)
{
	int size;
	char *compressed;
	z_stream stream;
	unsigned char sha1[20];
	SHA_CTX c;

	/* Set it up */
	memset(&stream, 0, sizeof(stream));
	deflateInit(&stream, Z_BEST_COMPRESSION);
	size = deflateBound(&stream, len);
	compressed = malloc(size);

	/* Compress it */
	stream.next_in = buf;
	stream.avail_in = len;
	stream.next_out = compressed;
	stream.avail_out = size;
	while (deflate(&stream, Z_FINISH) == Z_OK)
		/* nothing */;
	deflateEnd(&stream);
	size = stream.total_out;

	/* Sha1.. */
	SHA1_Init(&c);
	SHA1_Update(&c, compressed, size);
	SHA1_Final(sha1, &c);

	if (write_sha1_buffer(sha1, compressed, size) < 0)
		return -1;
	printf("%s\n", sha1_to_hex(sha1));
	return 0;
}

3.1 write_sha1_buffer(sha1, compressed, size); # 将组装的buffer信息压缩,然后对压缩值取hash,将压缩内容写入sha1文件

int write_sha1_buffer(unsigned char *sha1, void *buf, unsigned int size)
{
	char *filename = sha1_file_name(sha1);
	int i, fd;

	fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
	if (fd < 0)
		return (errno == EEXIST) ? 0 : -1;
	write(fd, buf, size);
	close(fd);
	return 0;
}

3.1.1 char *filename = sha1_file_name(sha1); # 根据hash值生成.dircache/objects/xx/xx..xx(38位)文件名

3.1.2 新建并将压缩数据写入sha1文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值