#pragma once #include #include #include #include #include struct git_repository; // Thrown for any libgit2 failure or invalid lookup. Handlers translate this // into an HTTP error response. class GitError : public std::runtime_error { public: explicit GitError(const std::string &what) : std::runtime_error(what) {} }; struct TreeEntry { std::string name; // last path component std::string path; // full path relative to repo root std::string oid; // hex object id bool is_dir = false; // tree bool is_submodule = false; uint64_t size = 0; // blob size in bytes (0 for non-blobs) }; struct CommitInfo { std::string oid; std::string short_oid; std::string summary; std::string author_name; std::string author_email; std::time_t time = 0; }; struct BlameLine { int number = 0; // 1-based line number std::string short_oid; // commit that last touched the line std::string author; std::time_t time = 0; std::string content; // the line text (without newline) }; struct TagInfo { std::string name; std::string target_oid; // commit the tag resolves to std::string short_oid; std::time_t time = 0; bool annotated = false; }; struct TagDetail { std::string name; std::string target_oid; std::string short_oid; bool annotated = false; std::string tagger_name; std::time_t time = 0; std::string message; }; struct FileChange { char status = '?'; // A, M, D, R, C, T std::string path; std::string old_path; // set for renames/copies }; struct DiffLine { std::string css; // CSS class: d-add, d-del, d-hunk, d-file, d-ctx std::string content; // line text (with +/- prefix for code lines) }; struct CommitDetail { std::string oid; std::string short_oid; std::string author_name; std::string author_email; std::time_t time = 0; std::string message; std::vector parents; std::string first_parent; // "" for a root commit; used for "before" links std::vector files; std::vector diff; }; enum class ObjectKind { Blob, Tree, Commit, Tag, Unknown }; struct ObjectView { ObjectKind kind = ObjectKind::Unknown; std::string oid; std::string type_name; std::string body; // textual summary or blob preview bool is_binary = false; std::vector entries; // populated for trees }; // libgit2 process-wide init/shutdown. Construct exactly once in main(). class GitLibrary { public: GitLibrary(); ~GitLibrary(); GitLibrary(const GitLibrary &) = delete; GitLibrary &operator=(const GitLibrary &) = delete; }; // Wraps a single opened repository. Not thread safe: open one per request. class GitRepo { public: explicit GitRepo(const std::string &path); ~GitRepo(); GitRepo(const GitRepo &) = delete; GitRepo &operator=(const GitRepo &) = delete; // Short name of the default branch (HEAD), e.g. "main". std::string default_branch() const; // Resolve a revision to a full commit oid. Empty id means HEAD. std::string resolve_commit(const std::string &id) const; // Directory listing of `path` ("" = root) at the given commit. std::vector list_tree(const std::string &commit_oid, const std::string &path) const; // Read a blob located at `path` within the commit tree. // Returns false if no such path exists. bool read_file(const std::string &commit_oid, const std::string &path, std::string &out, bool &is_binary) const; // First README* file at the root of the commit tree, or "" if none. std::string find_readme(const std::string &commit_oid) const; std::vector blame(const std::string &commit_oid, const std::string &path) const; std::vector log(const std::string &start_oid, int limit) const; // All tags, sorted by name. std::vector tags() const; // Details of a single tag by short name (e.g. "v1.0"). TagDetail tag_detail(const std::string &name) const; // Commit metadata plus the diff against its first parent. CommitDetail commit_detail(const std::string &oid) const; // The commit's diff as a raw unified patch. std::string commit_patch(const std::string &oid) const; // Inspect an arbitrary object by (possibly abbreviated) oid. ObjectView inspect(const std::string &oid) const; private: git_repository *repo_ = nullptr; };