-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathGitHash.java
More file actions
281 lines (225 loc) · 9.39 KB
/
GitHash.java
File metadata and controls
281 lines (225 loc) · 9.39 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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class GitHash {
// Create directories
public static void gitRepoInit() throws IOException {
GitHash.createDirectoryIfMissing("git");
GitHash.createDirectoryIfMissing("git/objects");
GitHash.createFileIfMissing("git/HEAD");
GitHash.createFileIfMissing("git/INDEX");
System.out.println("Git Repository Created");
}
public static void createDirectoryIfMissing(String path) throws IOException {
File directoryCreator = new File(path);
if (!directoryCreator.exists()) {
directoryCreator.mkdir();
} else {
System.out.println(path + " Already Exists");
}
}
public static void createFileIfMissing(String path) throws IOException {
File fileCreator = new File(path);
if (!fileCreator.exists()) {
fileCreator.createNewFile();
} else {
System.out.println(path + " Already Exists");
}
}
// SHA 1 && BLOB && INDEX
public static void add(String filePath) throws IOException {
File f = new File(filePath);
createBLOBAndAddToObjects(f);
addBLOBEntryToIndex(filePath);
}
public static String generateSHA1FromString(String contents) throws IOException {
File temp = new File("temp");
if (temp.exists()) {
temp.delete();
}
temp.createNewFile();
BufferedWriter bw = new BufferedWriter(new FileWriter(temp, true));
bw.write(contents);
bw.close();
return generateSHA1Hash(temp);
}
public static String generateSHA1Hash(File file) throws IOException {
byte[] bytes = Files.readAllBytes(file.toPath());
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(bytes);
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static void createBLOBAndAddToObjects(File file) throws IOException {
String hash = generateSHA1Hash(file);
File blob = new File("git/objects/" + hash);
blob.createNewFile();
FileOutputStream blobWriter = new FileOutputStream(blob);
BufferedReader fileCopier = new BufferedReader(new FileReader(file));
while (fileCopier.ready()) {
blobWriter.write(fileCopier.read());
}
fileCopier.close();
blobWriter.close();
}
public static void blobExists(File file) throws IOException {
String hash = generateSHA1Hash(file);
File blobChecker = new File("git/objects/" + hash);
if (blobChecker.exists()) {
System.out.println("BLOB " + hash + " of File " + file.getName() + " is in objects directory");
} else {
System.out.println(
"BLOB " + hash + " of File " + file.getName() + " does not exist or is not in objects directory");
}
}
public static void addBLOBEntryToIndex(String filePath) throws IOException {
BufferedWriter entryWriter = new BufferedWriter(new FileWriter("git/INDEX", true));
entryWriter.write(generateSHA1Hash(new File(filePath)) + " ./" + filePath + "\n");
entryWriter.close();
}
// REMOVERS
public static void deleteGitDirectory() throws IOException {
File indexDeleter = new File("git/INDEX");
indexDeleter.delete();
File headDeleter = new File("git/HEAD");
headDeleter.delete();
File objectsDeleter = new File("git/objects");
objectsDeleter.delete();
File gitDeleter = new File("git");
gitDeleter.delete();
System.out.println("Git Repository Deleted");
}
public static void deleteBLOBFromObjects(File file) throws IOException {
String hash = generateSHA1Hash(file);
File blobDeleter = new File("git/objects/" + hash);
blobDeleter.delete();
}
public static void cleanObjectsAndINDEX() throws IOException {
FileWriter overwriter = new FileWriter("git/INDEX");
overwriter.write("");
overwriter.close();
removeRecursively("objects", "git");
createDirectoryIfMissing("git/objects");
}
public static void removeRecursively(String pathName, String parentPathName) throws IOException {
File file = new File(parentPathName + "/" + pathName);
if (!file.exists()) {
return;
}
if (!file.isDirectory()) {
file.delete();
} else {
for (String childPathName : file.list()) {
removeRecursively(childPathName, parentPathName + "/" + pathName);
}
}
file.delete();
return;
}
// TREES
// saves all folders in index as tree objects
public static void stageFolders() throws IOException {
PriorityQueue<WorkingDirectoryInfo> wd = convertIndexToWorkingDirectory();
convertNestedDirs(wd);
}
// converts index to a PriorityQueue sorting from most to least imbedded in dirs. Info stored in Working Directory Function
public static PriorityQueue<WorkingDirectoryInfo> convertIndexToWorkingDirectory() throws IOException {
PriorityQueue<WorkingDirectoryInfo> wd = new PriorityQueue<>(Comparator.reverseOrder());
BufferedReader br = new BufferedReader(new FileReader("./git/INDEX"));
while (br.ready()) {
String info = br.readLine();
wd.add(new WorkingDirectoryInfo("blob", info.substring(0, info.indexOf(" ")), info.substring(info.indexOf(" ") + 1)));
}
br.close();
return wd;
}
// Goes through dirs in priority order (as mentioned above) and converts the contents into object
public static void convertNestedDirs(PriorityQueue<WorkingDirectoryInfo> wd) throws IOException {
if (wd.peek().size() != -1) {
ArrayList<WorkingDirectoryInfo> nestedFolders = new ArrayList<>();
nestedFolders.add(wd.poll());
WorkingDirectoryInfo currFolder = nestedFolders.get(0);
while (wd.peek() != null && wd.peek().isInSameFolder(currFolder)) {
nestedFolders.add(wd.poll());
}
String hash = writeTreeFile(convertContentsToString(nestedFolders));
wd.add(new WorkingDirectoryInfo("tree", hash, currFolder.getStringPath()));
convertNestedDirs(wd);
}
}
// converts an arraylist of working directory infos to a string
public static String convertContentsToString(ArrayList<WorkingDirectoryInfo> treeFiles) {
StringBuilder sb = new StringBuilder();
for (WorkingDirectoryInfo file : treeFiles) {
sb.append(file.getType() + " ");
sb.append(file.getHash() + " ");
sb.append(file.getFileName() + "\n");
}
return sb.toString().trim();
}
// stages all files inside a folder (i did this before i realized how to do the assignment)
public static String stageWHOLEfolder(File dir) throws IOException {
if (dir.exists() && dir.isDirectory() ) {
File[] contents = dir.listFiles();
String[][] workingList = new String[contents.length][3];
// stores info in a 2d array
for (int i = 0; i < contents.length; i++) {
File f = contents[i];
if (f.isDirectory() && f.listFiles().length != 0) {
workingList[i][0] = "tree";
workingList[i][1] = stageWHOLEfolder(f);
workingList[i][2] = f.getName();
}
if (!f.isDirectory()) {
workingList[i][0] = "blob";
workingList[i][1] = generateSHA1Hash(f);
workingList[i][2] = f.getName();
}
}
String hash = writeTreeFile(convertContentsToString(workingList));
return hash;
} else {
throw new IOException("Given file is not a directory/cannot be pushed");
}
}
// same as other one but for 2d arrays
public static String convertContentsToString(String[][] tree) {
StringBuilder sb = new StringBuilder();
for (String[] files : tree) {
if (files[0] != null) {
sb.append(files[0] + " ");
sb.append(files[1] + " ");
sb.append(files[2] + "\n");
}
}
return sb.toString().trim();
}
// writes a given string onto a file and names it a hash based on the contents
public static String writeTreeFile(String contents) throws IOException {
String hash = generateSHA1FromString(contents);
File folder = new File("./git/objects/" + hash);
if (!folder.exists()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(folder, true));
bw.write(contents);
bw.close();
}
return hash;
}
}