git repos / sago_web_git

src/repo_scanner.cpp

browsing at commit = 4fe276c400f51581a3858e55f7b9a48a1f90f419

raw · blame · history

#include "repo_scanner.h"

#include <filesystem>

namespace fs = std::filesystem;

namespace {

// A directory is a git repository if it contains a ".git" entry (normal repo)
// or looks like a bare repo (has HEAD and an objects directory).
bool is_repository(const fs::path &dir) {
    std::error_code ec;
    if (fs::exists(dir / ".git", ec))
        return true;
    return fs::exists(dir / "HEAD", ec) && fs::is_directory(dir / "objects", ec);
}

} // namespace

RepoScanner::RepoScanner(std::string root) : root_(std::move(root)) {
    std::error_code ec;
    if (!fs::is_directory(root_, ec))
        return;

    for (const fs::directory_entry &entry : fs::directory_iterator(root_, ec)) {
        if (!entry.is_directory(ec))
            continue;
        if (!is_repository(entry.path()))
            continue;
        repos_[entry.path().filename().string()] = entry.path().string();
    }
}

std::vector<std::string> RepoScanner::names() const {
    std::vector<std::string> result;
    result.reserve(repos_.size());
    for (const auto &[name, path] : repos_)
        result.push_back(name);
    return result;
}

std::string RepoScanner::path_for(const std::string &name) const {
    const auto it = repos_.find(name);
    if (it == repos_.end())
        return "";
    return it->second;
}