Files
branch_switcher/src/git_repository.cpp
daiqingshuang 31e632032f 重构
2025-05-27 16:52:47 +08:00

269 lines
8.3 KiB
C++

#include "git_repository.h"
#include "git_process_manager.h"
#include "task_manager.h"
#include <sstream>
#include <algorithm>
namespace git {
// 静态成员初始化
std::shared_ptr<ProcessManager> Repository::process_manager_ = std::make_shared<ProcessManager>();
Repository::Repository(const std::filesystem::path& path)
: name_(path.filename().string()), path_(path) {
}
Repository::~Repository() = default;
void Repository::ExecuteCommand(const std::string& cmd, Callback callback) {
process_manager_->ExecuteCommand(cmd, path_, callback);
}
void Repository::SwitchBranch(const std::string& branch, Callback callback) {
const std::string cmd = "checkout " + branch;
ExecuteCommand(cmd, [this, branch, callback](const Result& result) {
if (result.has_value()) {
// 更新缓存的分支名
{
std::unique_lock lock(cache_mutex_);
cached_branch_ = branch;
}
// 清除其他可能受影响的缓存
InvalidateCache();
}
// 确保回调在主线程执行
TaskManager::Get().ExecuteOnMainThread([callback, result]() {
callback(result);
});
});
}
void Repository::HardReset(Callback callback) {
ExecuteCommand("reset --hard", [callback](const Result& result) {
TaskManager::Get().ExecuteOnMainThread([callback, result]() {
callback(result);
});
});
}
void Repository::Pull(Callback callback) {
ExecuteCommand("pull", [callback](const Result& result) {
TaskManager::Get().ExecuteOnMainThread([callback, result]() {
callback(result);
});
});
}
void Repository::GetSubmodules(std::function<void(Submodules)> callback) {
// 先检查缓存
{
std::shared_lock lock(cache_mutex_);
if (cached_submodules_.has_value()) {
TaskManager::Get().ExecuteOnMainThread([callback, submodules = cached_submodules_.value()]() {
callback(submodules);
});
return;
}
}
// 异步获取子模块
ExecuteCommand("submodule", [this, callback](const Result& result) {
if (!result.has_value()) {
TaskManager::Get().ExecuteOnMainThread([callback, error = result.error()]() {
callback(std::unexpected(error));
});
return;
}
// 解析子模块
auto parse_future = TaskManager::Get().Execute([this, output = result.value()]() -> Submodules {
std::vector<std::shared_ptr<Repository>> submodules;
std::istringstream iss(output);
std::string line;
while (std::getline(iss, line)) {
// 解析格式: " 160000 commit-hash 0\tsubmodule-path"
// 或: "+160000 commit-hash 0\tsubmodule-path" (有修改)
// 或: "-160000 commit-hash 0\tsubmodule-path" (未初始化)
// 跳过空行
if (line.empty()) continue;
// 找到制表符位置
size_t tab_pos = line.find('\t');
if (tab_pos == std::string::npos) continue;
// 提取子模块路径
std::string submodule_path = line.substr(tab_pos + 1);
// 去除可能的尾部空格
submodule_path.erase(submodule_path.find_last_not_of(" \n\r\t") + 1);
if (!submodule_path.empty()) {
std::filesystem::path full_path = path_ / submodule_path;
auto submodule = std::make_shared<Repository>(full_path);
submodules.push_back(submodule);
}
}
return submodules;
});
// 处理解析结果
parse_future.wait();
auto submodules_result = parse_future.get();
if (submodules_result.has_value()) {
// 更新缓存
{
std::unique_lock lock(cache_mutex_);
cached_submodules_ = submodules_result.value();
}
}
// 在主线程回调
TaskManager::Get().ExecuteOnMainThread([callback, submodules_result]() {
callback(submodules_result);
});
});
}
void Repository::GetCurrentBranchName(std::function<void(Result)> callback) {
// 检查缓存
{
std::shared_lock lock(cache_mutex_);
if (cached_branch_.has_value()) {
TaskManager::Get().ExecuteOnMainThread([callback, branch = cached_branch_.value()]() {
callback(branch);
});
return;
}
}
// 异步获取当前分支
ExecuteCommand("rev-parse --abbrev-ref HEAD", [this, callback](const Result& result) {
if (!result.has_value()) {
TaskManager::Get().ExecuteOnMainThread([callback, error = result.error()]() {
callback(std::unexpected(error));
});
return;
}
// 处理结果
std::string branch_name = result.value();
// 去除尾部换行符
branch_name.erase(branch_name.find_last_not_of("\n\r") + 1);
// 更新缓存
{
std::unique_lock lock(cache_mutex_);
cached_branch_ = branch_name;
}
// 在主线程回调
TaskManager::Get().ExecuteOnMainThread([callback, branch_name]() {
callback(branch_name);
});
});
}
void Repository::GetAllBranches(std::function<void(Branches)> callback) {
// 检查缓存
{
std::shared_lock lock(cache_mutex_);
if (cached_branches_.has_value()) {
TaskManager::Get().ExecuteOnMainThread([callback, branches = cached_branches_.value()]() {
callback(branches);
});
return;
}
}
// 异步获取所有分支
ExecuteCommand("branch", [this, callback](const Result& result) {
if (!result.has_value()) {
TaskManager::Get().ExecuteOnMainThread([callback, error = result.error()]() {
callback(std::unexpected(error));
});
return;
}
// 解析分支列表
auto parse_future = TaskManager::Get().Execute([output = result.value()]() -> std::vector<std::string> {
std::vector<std::string> branches;
std::istringstream iss(output);
std::string line;
while (std::getline(iss, line)) {
if (!line.empty() && line.length() > 2) {
// 移除前面的 "* " 或 " "
std::string branch = line.substr(2);
// 去除尾部空白
branch.erase(branch.find_last_not_of(" \n\r\t") + 1);
if (!branch.empty()) {
branches.push_back(branch);
}
}
}
return branches;
});
// 等待解析完成
parse_future.wait();
auto branches = parse_future.get();
// 更新缓存
{
std::unique_lock lock(cache_mutex_);
cached_branches_ = branches;
}
// 在主线程回调
TaskManager::Get().ExecuteOnMainThread([callback, branches]() {
callback(branches);
});
});
}
std::optional<std::vector<std::shared_ptr<Repository>>> Repository::GetCachedSubmodules() const {
std::shared_lock lock(cache_mutex_);
return cached_submodules_;
}
std::optional<std::string> Repository::GetCachedBranchName() const {
std::shared_lock lock(cache_mutex_);
return cached_branch_;
}
std::optional<std::vector<std::string>> Repository::GetCachedBranches() const {
std::shared_lock lock(cache_mutex_);
return cached_branches_;
}
bool Repository::IsValid() const {
return std::filesystem::exists(path_ / ".git");
}
void Repository::InvalidateCache() {
std::unique_lock lock(cache_mutex_);
// 只清除可能受影响的缓存
// 分支切换不会影响子模块列表,所以保留 cached_submodules_
cached_branches_.reset();
// cached_branch_ 在 SwitchBranch 中已更新,不需要清除
}
std::shared_ptr<Repository> OpenRepository(const std::filesystem::path& path) {
auto repo = std::make_shared<Repository>(path);
if (repo->IsValid()) {
return repo;
}
return nullptr;
}
} // namespace git