basic-vcs/src/commands/ls-tree.cpp

75 lines
2.2 KiB
C++

#include "ls-tree.h"
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string>
#include <string_view>
#include "zstr.hpp"
int lsTree(const int argc, const char** argv)
{
bool nameOnly = false;
if (argc == 4)
{
const std::string flag = argv[2];
if (flag != "--name-only")
{
std::cerr << flag << "is an invalid flag, please use \"--name-only\"\n";
return 1;
}
nameOnly = true;
}
const std::string input = nameOnly ? argv[3] : argv[2];
const std::string dir = input.substr(0, 2);
const std::string file = input.substr(2);
zstr::ifstream inputFile("./.git/objects/" + dir + "/" + file, std::ofstream::binary);
if (!inputFile.is_open())
{
std::cerr << "Could not open file\n";
return 1;
}
const std::string output{std::istreambuf_iterator<char>(inputFile), std::istreambuf_iterator<char>()};
//start right after tree <size>\0
size_t startChar = output.find('\0') + 1;
size_t nextNullChar = output.find('\0', startChar);
while (nextNullChar != std::string::npos)
{
const std::string_view modeAndName = std::string_view(output).substr(startChar, nextNullChar - startChar);
const std::string_view mode = modeAndName.substr(0, modeAndName.find(' '));
const std::string_view name = modeAndName.substr(modeAndName.find(' ') + 1);
const std::string_view hash = std::string_view(output).substr(nextNullChar + 1, 20);
if (!nameOnly)
{
if (mode == "100644" or mode == "100755")
{
std::cout << mode << ' ';
std::cout << "blob ";
}
else
{//assume it's a tree obj
std::cout << "0" << mode << ' ';
std::cout << "tree ";
}
for (const auto& value : hash)
std::printf("%02x", static_cast<unsigned char>(value)); // simpler solution
std::cout << " ";
}
std::cout << name << "\n";
startChar = nextNullChar + 21;
nextNullChar = output.find('\0', startChar);
}
inputFile.close();
return 0;
}