I’m stuck on Stage #FE4 git write-tree
My write-tree command creates all object files as I expect and they can be read using ls-tree command and it shows the expected result, but the hash differs from the one generated by git write-tree. And if I try to read it using real git I get “error: hash mismatch 72b8d28613c74fcffa26d7fcf662d01880a3e952”.
Here are my logs:
remote: [tester::#FE4] Expected (bytes 0-100), hexadecimal: | ASCII:
remote: [tester::#FE4] 74 72 65 65 20 31 30 31 00 31 30 30 36 34 34 20 64 75 6d 70 | tree 101.100644 dump
remote: [tester::#FE4] 74 79 00 f0 51 9d dc d6 b8 40 86 ea 99 cd 92 65 50 87 3f 81 | ty..Q....@.....eP.?.
remote: [tester::#FE4] 12 2f be 34 30 30 30 30 20 68 6f 72 73 65 79 00 b5 ef 33 bb | ./.40000 horsey...3.
remote: [tester::#FE4] f0 a8 2a 9b 85 d1 0a be 61 9a eb 02 6f 65 e9 0d 34 30 30 30 | ..*.....a...oe..4000
remote: [tester::#FE4] 30 20 76 61 6e 69 6c 6c 61 00 d1 fb d0 01 14 d4 11 32 39 f5 | 0 vanilla........29.
remote: [tester::#FE4]
remote: [tester::#FE4] Actual (bytes 0-100), hexadecimal: | ASCII:
remote: [tester::#FE4] 74 72 65 65 20 31 36 31 00 31 30 30 36 34 34 20 64 75 6d 70 | tree 161.100644 dump
remote: [tester::#FE4] 74 79 00 66 30 35 31 39 64 64 63 64 36 62 38 34 30 38 36 65 | ty.f0519ddcd6b84086e
remote: [tester::#FE4] 61 39 39 63 64 39 32 36 35 35 30 38 37 33 66 38 31 31 32 32 | a99cd926550873f81122
remote: [tester::#FE4] 66 62 65 34 30 30 30 30 20 68 6f 72 73 65 79 00 36 34 35 62 | fbe40000 horsey.645b
remote: [tester::#FE4] 32 35 65 35 36 65 32 63 31 30 37 34 33 64 38 35 61 66 37 66 | 25e56e2c10743d85af7f
And here’s a snippet of my code:
System.out.print(writeTree(new File(".")));
private String writeTree(File file) {
File[] files = file.listFiles();
Arrays.sort(files);
StringBuilder treeContent = new StringBuilder();
for (File f : files) {
if (f.getName().equals(".git")) {
continue;
}
String hash;
String mode;
if (f.isDirectory()) {
hash = processDir(f);
mode = "40000";
} else {
hash = createObjectFromFile(f.getPath(), true);
mode = "100644";
}
String entry = String.format("%s %s\0%s", mode, f.getName(), hash);
treeContent.append(entry);
}
byte[] content = treeContent.toString().getBytes();
String hash = hashObjectProcessor.hash(content);
byte[] header = ("tree " + content.length).getBytes();
hashObjectProcessor.createObjectFile(hash, header, content);
return hash;
}
public String hash(byte[] content) {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update("blob ".getBytes());
digest.update(String.valueOf(content.length).getBytes());
digest.update(new byte[]{0});
byte[] hash = digest.digest(Arrays.copyOf(content, content.length));
return HexFormat.of().formatHex(hash);
}
public String createObjectFromFile(String fileName, boolean needWrite) {
final File file = new File(fileName);
byte[] content;
try (FileInputStream fio = new FileInputStream(file)) {
content = fio.readAllBytes();
}
String hash = hash(content);
if (needWrite) {
byte[] header = ("blob " + content.length).getBytes();
createObjectFile(hash, header, content);
}
return hash;
}
public void createObjectFile(String hash, byte[] header, byte[] content) {
File root = new File(".git/objects");
new File(root, hash.substring(0, 2)).mkdirs();
final File object = new File(root, hash.substring(0, 2) + "/" + hash.substring(2));
object.createNewFile();
byte[] output = new byte[header.length + content.length + 1];
System.arraycopy(header, 0, output, 0, header.length);
output[header.length] = 0x00;
System.arraycopy(content, 0, output, header.length + 1, content.length);
output = ZLibUtils.compress(output);
try (FileOutputStream fos = new FileOutputStream(object)) {
fos.write(output);
}
}