/
commit.c
128 lines (104 loc) · 3.66 KB
/
commit.c
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "commit.h"
#include "object.h"
#include "path.h"
#include "tree.h"
char *write_commit() {
char *tmpcommit_path = get_repo_troll_dir();
tmpcommit_path = (char *) realloc(tmpcommit_path, strlen(tmpcommit_path) + 10);
strcat(tmpcommit_path, "tmpcommit");
int tmpcommitfd = open(tmpcommit_path, O_RDONLY, 0644);
free(tmpcommit_path);
struct stat buf;
fstat(tmpcommitfd, &buf);
char *data = (char *) malloc((size_t) buf.st_size + 17);
sprintf(data, "commit %lu", (unsigned long) buf.st_size);
int left_part_len = strlen(data) + 1;
read(tmpcommitfd, data + left_part_len, buf.st_size);
close(tmpcommitfd);
int full_len = left_part_len + buf.st_size;
char *hash = hash_object(data, full_len);
char *path = get_repo_troll_dir();
path = (char *) realloc(path, strlen(path) + 49); // Path + "objects/" + 40 digit hash + null terminator
strcat(path, "objects/");
strncat(path, hash, 40);
/* Create object file */
int objectfd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0644);
write(objectfd, data, full_len);
return hash;
}
void commit(const char *message) {
char *tmpcommit_path = get_repo_troll_dir();
tmpcommit_path = (char *) realloc(tmpcommit_path, strlen(tmpcommit_path) + 10);
strcat(tmpcommit_path, "tmpcommit");
char *treehash = write_tree();
int tmpcommitfd = open(tmpcommit_path, O_CREAT | O_TRUNC | O_WRONLY, 0644);
free(tmpcommit_path);
write(tmpcommitfd, "tree ", 5);
write(tmpcommitfd, treehash, 40);
char *path = get_repo_troll_dir();
path = (char *) realloc(path, strlen(path) + 7);
strcat(path, "master");
int masterfd = open(path, O_CREAT | O_RDWR, 0644);
struct stat buf;
fstat(masterfd, &buf);
if (buf.st_size > 0) {
write(tmpcommitfd, "\nparent ", 8);
char *parenthash = (char *) malloc(41 * sizeof(char));
read(masterfd, parenthash, 40);
write(tmpcommitfd, parenthash, 40);
}
write(tmpcommitfd, "\nauthor ", 8);
write(tmpcommitfd, getenv("USER"), strlen(getenv("USER")));
write(tmpcommitfd, "\n\n", 2);
write(tmpcommitfd, message, strlen(message));
write(tmpcommitfd, "\n", 1);
close(tmpcommitfd);
char *hash = write_commit();
/* Update master ref */
lseek(masterfd, 0, SEEK_SET);
write(masterfd, hash, 40);
char *headpath = get_repo_troll_dir();
headpath = (char *) realloc(headpath, strlen(path) + 5);
strcat(headpath, "HEAD");
int headfd = open(headpath, O_CREAT | O_RDWR, 0644);
struct stat headbuf;
fstat(headfd, &headbuf);
if (headbuf.st_size == 0) {
write(headfd, "master", 6);
}
printf("[master %.7s] %s\n", hash, message);
}
char *get_parent(char *hash) {
char *obj_path = get_repo_troll_dir();
obj_path = (char *) realloc(obj_path, strlen(obj_path) + 49);
strcat(obj_path, "objects/");
strncat(obj_path, hash, 40);
int objectfd = open(obj_path, O_RDONLY);
if (errno == ENOENT) {
printf("fatal: Object does not exist.\n");
exit(128);
}
struct stat buf;
fstat(objectfd, &buf);
char *data = (char *) malloc((size_t) buf.st_size + 1);
read(objectfd, data, buf.st_size);
char *data_right = data + strlen(data) + 1;
char *parent_hash = strstr(data_right, "parent");
if (parent_hash) {
parent_hash += 7;
char *hashcpy = (char *) malloc(41 * sizeof(char));
strncpy(hashcpy, parent_hash, 40);
free(data);
return hashcpy;
}
free(data);
return NULL;
}