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文件