269 lines
8.3 KiB
C++
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
|