#include "write-tree.h" #include #include #include #include #include #include "sha1.hpp" #include "zstr.hpp" struct node { std::string name; int mode; std::string hash; }; uint8_t hexToRaw(const char firstDigit, const char secondDigit) { uint8_t result = 0; switch (firstDigit) { case '0': result = 0x0; break; case '1': result = 0x1 << 4; break; case '2': result = 0x2 << 4; break; case '3': result = 0x3 << 4; break; case '4': result = 0x4 << 4; break; case '5': result = 0x5 << 4; break; case '6': result = 0x6 << 4; break; case '7': result = 0x7 << 4; break; case '8': result = 0x8 << 4; break; case '9': result = 0x9 << 4; break; case 'a': result = 0xa << 4; break; case 'b': result = 0xb << 4; break; case 'c': result = 0xc << 4; break; case 'd': result = 0xd << 4; break; case 'e': result = 0xe << 4; break; case 'f': result = 0xf << 4; break; default: result = 0; break; } switch (secondDigit) { case '0': result |= 0x0; break; case '1': result |= 0x1; break; case '2': result |= 0x2; break; case '3': result |= 0x3; break; case '4': result |= 0x4; break; case '5': result |= 0x5; break; case '6': result |= 0x6; break; case '7': result |= 0x7; break; case '8': result |= 0x8; break; case '9': result |= 0x9; break; case 'a': result |= 0xa; break; case 'b': result |= 0xb; break; case 'c': result |= 0xc; break; case 'd': result |= 0xd; break; case 'e': result |= 0xe; break; case 'f': result |= 0xf; break; default: result = 0; break; } return result; } std::string hashDir(const std::string& path) { std::vector nodes; for (const auto& object : std::filesystem::directory_iterator(path)) { if (object.is_directory()) {//recurse into the directory nodes.emplace_back(object.path().filename().string(), 40000, hashDir(object.path().string())); } else { std::ifstream file(object.path().string()); std::string fileContent {std::istreambuf_iterator(file), std::istreambuf_iterator()}; SHA1 checksum; checksum.update("blob " + std::to_string(fileContent.size()) + '\0' + fileContent); nodes.emplace_back(object.path().filename(), 100644, checksum.final()); file.close(); } } std::sort(nodes.begin(), nodes.end(), [](const auto& first, const auto& second){return first.name < second.name;}); std::string treeObject; for (const auto&[name, mode, hash] : nodes) { treeObject += std::to_string(mode) + " " + name + '\0'; for (int i = 0; i < 39; i += 2) { uint8_t byte = hexToRaw(hash.at(i), hash.at(i+1)); treeObject += static_cast(byte); } } treeObject = "tree " + std::to_string(treeObject.size()) + '\0' + treeObject; SHA1 checksum; checksum.update(treeObject); return checksum.final(); } int writeTree(const char** argv) { if (!std::filesystem::exists("./.git/objects")) std::filesystem::create_directory("./.git/objects"); std::vector nodes; for (const auto& object : std::filesystem::directory_iterator("./")) { if (object.path().filename() == ".git") continue; if (object.is_directory()) {//recurse into the directory nodes.emplace_back(object.path().filename().string(), 40000, hashDir(object.path().string())); } else { std::ifstream file(object.path().string()); std::string fileContent {std::istreambuf_iterator(file), std::istreambuf_iterator()}; SHA1 checksum; checksum.update("blob " + std::to_string(fileContent.size()) + '\0' + fileContent); nodes.emplace_back(object.path().filename(), 100644, checksum.final()); file.close(); } } std::sort(nodes.begin(), nodes.end(), [](const auto& first, const auto& second){return first.name < second.name;}); std::string treeObject; for (const auto&[name, mode, hash] : nodes) { treeObject += std::to_string(mode) + " " + name + '\0'; for (int i = 0; i < 39; i += 2) { uint8_t byte = hexToRaw(hash.at(i), hash.at(i+1)); treeObject += static_cast(byte); } } treeObject = "tree " + std::to_string(treeObject.size()) + '\0' + treeObject; SHA1 checksum; checksum.update(treeObject); const std::string hash = checksum.final(); std::cout << hash << "\n"; const std::string hashDir = "./.git/objects/" + hash.substr(0,2); if (!std::filesystem::exists(hashDir)) { std::filesystem::create_directory(hashDir); } zstr::ofstream outputFile(hashDir + "/" + hash.substr(2)); outputFile.write(treeObject.c_str(), treeObject.size()); outputFile.close(); return 0; }