-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommit.c
More file actions
94 lines (80 loc) · 3.01 KB
/
commit.c
File metadata and controls
94 lines (80 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "mvcs.h"
/* Write commit object */
int write_commit(const commit_t *commit, unsigned char *hash) {
char buffer[4096];
char tree_hex[HASH_HEX_SIZE];
char parent_hex[HASH_HEX_SIZE];
hash_to_hex(commit->tree_hash, tree_hex);
int len;
if (commit->has_parent) {
hash_to_hex(commit->parent_hash, parent_hex);
len = snprintf(buffer, sizeof(buffer),
"tree %s\nparent %s\nauthor %s\ntime %ld\n\n%s",
tree_hex, parent_hex, commit->author,
commit->timestamp, commit->message);
} else {
len = snprintf(buffer, sizeof(buffer),
"tree %s\nauthor %s\ntime %ld\n\n%s",
tree_hex, commit->author,
commit->timestamp, commit->message);
}
return write_object(OBJ_COMMIT, buffer, len, hash);
}
/* Read commit object */
int read_commit(const unsigned char *hash, commit_t *commit) {
int type;
void *data;
size_t len;
if (read_object(hash, &type, &data, &len) != 0 || type != OBJ_COMMIT) {
return -1;
}
char *content = (char *)data;
char tree_hex[HASH_HEX_SIZE];
char parent_hex[HASH_HEX_SIZE];
/* Parse commit data */
commit->has_parent = 0;
commit->message[0] = '\0';
/* Find the blank line separating headers from message */
char *msg_start = strstr(content, "\n\n");
if (msg_start) {
msg_start += 2; /* Skip the two newlines */
strncpy(commit->message, msg_start, sizeof(commit->message) - 1);
commit->message[sizeof(commit->message) - 1] = '\0';
/* Remove trailing garbage by finding actual end */
size_t msg_len = strlen(msg_start);
if (msg_len < sizeof(commit->message)) {
commit->message[msg_len] = '\0';
}
}
/* Parse headers line by line */
char *line_end;
char *line = content;
while (line && *line) {
line_end = strchr(line, '\n');
if (line_end) {
*line_end = '\0';
}
if (strlen(line) == 0) {
break; /* End of headers */
}
if (strncmp(line, "tree ", 5) == 0) {
strncpy(tree_hex, line + 5, sizeof(tree_hex) - 1);
tree_hex[sizeof(tree_hex) - 1] = '\0';
hex_to_hash(tree_hex, commit->tree_hash);
} else if (strncmp(line, "parent ", 7) == 0) {
strncpy(parent_hex, line + 7, sizeof(parent_hex) - 1);
parent_hex[sizeof(parent_hex) - 1] = '\0';
hex_to_hash(parent_hex, commit->parent_hash);
commit->has_parent = 1;
} else if (strncmp(line, "author ", 7) == 0) {
strncpy(commit->author, line + 7, sizeof(commit->author) - 1);
commit->author[sizeof(commit->author) - 1] = '\0';
} else if (strncmp(line, "time ", 5) == 0) {
commit->timestamp = atol(line + 5);
}
if (!line_end) break;
line = line_end + 1;
}
free(data);
return 0;
}