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

82 lines
2.3 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::filesystem::path dir {input.substr(0, 2)};
const std::string file {input.substr(2)};
const std::filesystem::path fullPath{ std::filesystem::current_path() / ".git/objects/" / dir / file };
zstr::ifstream inputFile(fullPath.string(), 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)); // easy way to display raw bytes as hex chars
std::cout << " ";
}
std::cout << name << "\n";
startChar = nextNullChar + 21;
nextNullChar = output.find('\0', startChar);
}
inputFile.close();
return 0;
}