-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
147 lines (127 loc) · 3.74 KB
/
main.cpp
File metadata and controls
147 lines (127 loc) · 3.74 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
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#include "./utils/sha1.h"
#include "utils/zstr.hpp"
using namespace std;
int git_init();
int git_hash_object(char* path);
int git_commit();
int git_cat_file(char* flag, char* sha);
int main(int argc, char **argv)
{
cout << unitbuf;
cerr << unitbuf;
if (argc < 2 )
{
cout << "Not enough arguments!" << endl;
return EXIT_FAILURE;
}
string command = argv[1];
if (command == "init")
{
return git_init();
}
else if (command == "hash-object")
{
//this is not an actual command (or even if it is, it doesn't do that)
//this thing only stores the files as git objects in the .git/objects folder
if (command == "hash-object") {
for (int i = 2; i < argc; i++) {
git_hash_object(argv[i]);
}
}
}
else if (command == "cat-file")
{
return git_cat_file(argv[2], argv[3]);
}
else
{
cout << "Unknown command: " << command << endl;
return EXIT_FAILURE;
}
}
int git_init()
{
try
{
filesystem::create_directory("./.git");
filesystem::create_directory("./.git/objects");
filesystem::create_directory("./.git/refs");
ofstream head_file("./.git/HEAD");
cout << "Initialized empty git repository." << endl;
return EXIT_SUCCESS;
}
catch (exception &e)
{
cerr << "Error initializing repository: " << e.what() << endl;
return EXIT_FAILURE;
}
}
int git_hash_object(char* path)
{
if (!filesystem::exists(path))
{
cerr << "Error: File " << path << " does not exist." << endl;
return EXIT_FAILURE;
}
ifstream f(path, ios::binary);
vector<uint8_t> content((istreambuf_iterator<char>(f)), istreambuf_iterator<char>());
string header = "blob" + to_string(content.size()) + '\0';
vector<uint8_t> blob;
blob.insert(blob.end(), header.begin(), header.end());
blob.insert(blob.end(), content.begin(), content.end());
SHA1_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, blob.data(), blob.size());
uint8_t digest[SHA1_DIGEST_SIZE];
SHA1_Final(&ctx, digest);
string sha1hex; //this will have the 40char hex representation of the sha1 digest
for (int i = 0; i < SHA1_DIGEST_SIZE; i++)
{
char buf[3];
sprintf(buf, "%02x", digest[i]);
sha1hex += buf;
}
string dir = "./.git/objects/" + sha1hex.substr(0, 2);
string file = dir + "/" + sha1hex.substr(2);
filesystem::create_directories(dir);
zstr::ofstream out(file);
out.write(reinterpret_cast<const char*>(blob.data()), blob.size());
out.close();
cout << "Added file " << path << " as blob " << sha1hex << endl;
return EXIT_SUCCESS;
}
int git_commit()
{
// Placeholder for future implementation
return EXIT_SUCCESS;
}
int git_cat_file(char* flag, char* sha)
{
if (flag != string("-p"))
{
cerr << "Error: Unsupported flag " << flag << endl;
return EXIT_FAILURE;
}
string dir = "./.git/objects/" + string(sha).substr(0, 2);
string obj = dir + "/" + string(sha).substr(2);
if (!filesystem::exists(obj))
{
cerr << "Error: Object " << sha << " does not exist." << endl;
return EXIT_FAILURE;
}
zstr::ifstream file(obj);
std::string decompressed_content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
size_t null_pos = decompressed_content.find('\0');
if (null_pos == string::npos)
{
cerr << "Error: Invalid object format." << endl;
return EXIT_FAILURE;
}
string content = decompressed_content.substr(null_pos + 1);
cout << content << endl;
return EXIT_SUCCESS;
}