I’m stuck on Stage #(FE4)
I’ve tried multiple solutions from the solved examples but I am not able to pass.
Here are my logs:
[tester::#FE4] Running tests for Stage #FE4 (Write a tree object)
remote: [tester::#FE4] $ ./your_git.sh init
remote: [your_program] Initialized git directory
remote: [tester::#FE4] Creating some files & directories
remote: [tester::#FE4] $ ./your_git.sh write-tree
remote: [your_program] 801923b6ac7e55825b73e85ecbeaf26da256505d65496b5b730f2784a1129f210c65eddf53e94c55ca40a0d504bd1b82f45d397fad62dab9563190570bf21250eee4dce73d38daa7b534ae98c9d5056d7f192d74684a2148b7a639b7e1516a244df951a6
remote: [tester::#FE4] Expected a 40-char SHA as output. Got: 801923b6ac7e55825b73e85ecbeaf26da256505d65496b5b730f2784a1129f210c65eddf53e94c55ca40a0d504bd1b82f45d397fad62dab9563190570bf21250eee4dce73d38daa7b534ae98c9d5056d7f192d74684a2148b7a639b7e1516a244df951a6
And here’s a snippet of my code:
const fs = require("fs");
const path = require("path");
const zlib = require("zlib")
const crypto = require("crypto")
const command = process.argv[2];
switch (command) {
case "init":
createGitDirectory();
break;
case "cat-file":
readBlobObject(process.argv[4]);
break;
case "hash-object":
writeBlobObject(process.argv[4]);
break;
case "ls-tree":
listTreeContent(process.argv[4]);
break;
case "write-tree":
process.stdout.write(writeTreeObject(process.cwd()).toString('hex'));
break;
default:
throw new Error(`Unknown command ${command}`);
}
function createGitDirectory() {
fs.mkdirSync(path.join(process.cwd(), ".git"), { recursive: true });
fs.mkdirSync(path.join(process.cwd(), ".git", "objects"), { recursive: true });
fs.mkdirSync(path.join(process.cwd(), ".git", "refs"), { recursive: true });
fs.writeFileSync(path.join(process.cwd(), ".git", "HEAD"), "ref: refs/heads/main\n");
console.log("Initialized git directory");
}
function readBlobObject(blobHash) {
const filePath = sliceHash(blobHash)
const compressedData = (fs.readFileSync(`.git/objects/${filePath}`));
const decompressedData = decompressData(compressedData);
const blobContent = extractContent(decompressedData);
process.stdout.write(blobContent)
}
function sliceHash(Hash){
return Hash.slice(0,2) + '/' + Hash.slice(2);
}
function decompressData(compressedData){
return zlib.inflateSync(compressedData);
}
function extractContent(decompressedData){
return decompressedData.toString().split('\0')[1];
}
function writeBlobObject(file){
const fileActualContent = fs.readFileSync(file);
const fileContent = `blob ${fileActualContent.length}\0${fileActualContent}`;
const blobHash = createShaHash(fileContent)
const filePath = sliceHash(blobHash)
const compressedData = zlib.deflateSync(fileContent);
createObject(filePath,compressedData);
process.stdout.write(blobHash)
const sha = createShaBinary(fileContent);
return sha;
}
function createObject(objectSubPath,compressedData){
fs.mkdirSync(`.git/objects/${objectSubPath.split('/')[0]}`, { recursive : true})
fs.writeFileSync(`.git/objects/${objectSubPath}`,compressedData);
}
function createShaHash(data){
const shaHash = crypto.createHash('sha1');
shaHash.update(data);
return shaHash.digest('hex');
}
function createShaBinary(data){
const shaHash = crypto.createHash('sha1');
shaHash.update(data);
return shaHash.digest();
}
function listTreeContent(shaHash){
const filePath = sliceHash(shaHash);
const fileContent = decompressData(fs.readFileSync(`.git/objects/${filePath}`));
const tree = fileContent.toString().split("\0").slice(1);
const fileNames = [];
for(let i = 0; i < tree.length; i++){
fileNames.push(tree[i].split(' ')[1]);
}
process.stdout.write(fileNames.join("\n"));
}
function parseTree(dir){
return fs.readdirSync(dir)
.filter((file) => file !== ".git")
.map((file) => {
const fullPath = path.join(dir,file);
if(fs.lstatSync(fullPath).isDirectory()){
return {
mode: 40000,
name: file,
hash: writeTreeObject(fullPath).toString('binary'),
};
}
return {
mode: 100644,
name: file,
hash: writeBlobObject(fullPath).toString('binary'),
};
});
}
function writeTreeObject(dirPath) {
const tree = parseTree(dirPath);
const treeContent = tree.reduce((acc,{mode, name, hash})=>
Buffer.concat([
acc,
Buffer.from(`${mode} ${name}\0`),
Buffer.from(hash , 'binary'),
])
,Buffer.alloc(0));
const treeObject = Buffer.concat([
Buffer.from(`tree ${treeContent.length}\0`),
treeContent
]);
const treeHash = createShaHash(treeObject);
const compressedData = zlib.deflateSync(treeObject);
const subDirectory = treeHash.slice(0,2);
const fileName = treeHash.slice(2);
const sha = createShaBinary(treeObject);
if(!fs.existsSync(path.resolve(".git", "objects",subDirectory))){
fs.mkdirSync(path.resolve(".git", "objects",subDirectory));
}
fs.writeFileSync(path.resolve(".git", "objects",subDirectory,fileName), compressedData);
return sha;
}