From 133424f5f830e7f46554a5b285f3b7a5d0ac7879 Mon Sep 17 00:00:00 2001 From: asypost Date: Sat, 18 Jul 2026 16:40:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + include/seafile/fs/seafile_file_system.hpp | 4 +- include/seafile/fs/seafile_store.hpp | 29 +++-- include/seafile/fs/storage/repo_entry.hpp | 9 +- src/main.cpp | 1 - src/seafile/fs/seafile_store.cpp | 128 ++++++++++++++++++--- src/seafile/fs/storage/repo_entry.cpp | 31 +++++ 7 files changed, 169 insertions(+), 34 deletions(-) create mode 100644 src/seafile/fs/storage/repo_entry.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6839fc2..a5e91c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ add_executable(seadisk src/main.cpp include/seafile/fs/seafile_store.hpp src/seafile/fs/seafile_store.cpp include/seafile/fs/storage/repo_entry.hpp + src/seafile/fs/storage/repo_entry.cpp ) target_compile_definitions(seadisk PRIVATE diff --git a/include/seafile/fs/seafile_file_system.hpp b/include/seafile/fs/seafile_file_system.hpp index 0c830d6..047ff62 100644 --- a/include/seafile/fs/seafile_file_system.hpp +++ b/include/seafile/fs/seafile_file_system.hpp @@ -7,8 +7,8 @@ #include #include -#include "../api/seafile_api.hpp" -#include "../api/token_type.hpp" +#include "seafile/api/seafile_api.hpp" +#include "seafile/api/token_type.hpp" #include "seafile/api/cached_seafile_api.hpp" #include "seafile/cache/cache.hpp" diff --git a/include/seafile/fs/seafile_store.hpp b/include/seafile/fs/seafile_store.hpp index 36e7721..74d584e 100644 --- a/include/seafile/fs/seafile_store.hpp +++ b/include/seafile/fs/seafile_store.hpp @@ -9,38 +9,43 @@ #include "storage/repo_entry.hpp" -namespace seafile::fs { - - - class SeafileStore final { +namespace seafile::fs +{ + class SeafileStore final + { public: - /// construction /// @param db_path database file path /// @param server the server url of seafile /// @param user user /// @param password password - SeafileStore(const std::string &db_path, const std::string &server, const std::string &user, - const std::string &password); + SeafileStore(const std::string& db_path, const std::string& server, const std::string& user, + const std::string& password); - SeafileStore(const SeafileStore &) = default; + SeafileStore(const SeafileStore&) = delete; - tl::expected auth(); + tl::expected auth(); + + [[nodiscard]] tl::expected defaultRepoId() const; + + ///初始化数据库信息 + [[nodiscard]] tl::expected init() const; /// 检查是否已经更新到最新 /// @return true 已经最新,false 需要更新 tl::expected checkIsUpdated(const std::string& repo_id); /// 检查是否需要更新元素据,如果需要同步则自动同步 - tl::expected checkAndSync(const std::string& repo_id,); + tl::expected checkAndSync(const std::string& repo_id); /// 同步元数据 - tl::expected sync(const std::string& repo_id); + [[nodiscard]] tl::expected sync(const std::string& repo_id) const; /// 获取路径信息 /// @param path 路径 /// @return 路径信息 - tl::expected findRepoEntry(const std::string& repo_id, const std::string &path); + tl::expected findRepoEntry( + const std::string& repo_id, const std::string& path); private: struct Database; diff --git a/include/seafile/fs/storage/repo_entry.hpp b/include/seafile/fs/storage/repo_entry.hpp index 0632c03..a48033d 100644 --- a/include/seafile/fs/storage/repo_entry.hpp +++ b/include/seafile/fs/storage/repo_entry.hpp @@ -7,8 +7,10 @@ #include "seafile/api/repo_entry.hpp" #include -namespace seafile::fs::storage { - struct RepoEntry final { +namespace seafile::fs::storage +{ + struct RepoEntry final + { ///repo id std::string repo_id; @@ -56,6 +58,9 @@ namespace seafile::fs::storage { /// Whether the entry is starred by the current user. std::optional starred{}; + + static auto from_api_model(const std::string& repo_id, const std::string& path, + const api::RepoEntry& entry) -> RepoEntry; }; } #endif //SEADISK_STORAGE_REPO_ENTRY_HPP diff --git a/src/main.cpp b/src/main.cpp index 2493ad4..837abae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,5 @@ #include #include "seafile/fs/winfsp_adapter.hpp" -#include "seafile/api/seafile_api.hpp" using namespace seafile::fs; diff --git a/src/seafile/fs/seafile_store.cpp b/src/seafile/fs/seafile_store.cpp index 587cae5..ca27cd5 100644 --- a/src/seafile/fs/seafile_store.cpp +++ b/src/seafile/fs/seafile_store.cpp @@ -6,17 +6,21 @@ #include "seafile/api/account_info.hpp" #include "seafile/api/repo_info.hpp" #include "seafile/fs/storage/repo_entry.hpp" +#include // // Created by Shell on 2026/7/16. // -namespace seafile::fs { +namespace seafile::fs +{ using RepoEntry = storage::RepoEntry; using AccountInfo = api::AccountInfo; using RepoInfo = api::RepoInfo; - namespace { - auto make_storage(const std::string &path) { + namespace + { + auto make_storage(const std::string& path) + { // clang-format off return sqlite_orm::make_storage(path, sqlite_orm::make_table("account_info", @@ -75,17 +79,34 @@ namespace seafile::fs { } } - struct SeafileStore::Database { + struct SeafileStore::Database + { using Storage = decltype(make_storage("")); Storage storage; - explicit Database(const std::string &path) - : storage(make_storage(path)) { + explicit Database(const std::string& path) + : storage(make_storage(path)) + { } }; - SeafileStore::SeafileStore(const std::string &db_path, const std::string &server, const std::string &user, - const std::string &password) : api(server) { + tl::expected SeafileStore::auth() + { + if (const auto auth_info = this->api.authToken(this->user, this->password)) + { + this->token = auth_info->token; + this->token_type = api::TokenType::TOKEN; + return {}; + } + else + { + return tl::make_unexpected(api::SeafileException(auth_info.error())); + } + } + + SeafileStore::SeafileStore(const std::string& db_path, const std::string& server, const std::string& user, + const std::string& password) : api(server) + { this->database = std::make_unique(db_path); this->user = user; this->password = password; @@ -93,8 +114,9 @@ namespace seafile::fs { } tl::expected SeafileStore::findRepoEntry( - const std::string &repo_id, const std::string &path) { - auto &storage = this->database->storage; + const std::string& repo_id, const std::string& path) + { + auto& storage = this->database->storage; const auto entry = storage.get_optional( sqlite_orm::where( sqlite_orm::and_( @@ -102,27 +124,99 @@ namespace seafile::fs { sqlite_orm::c(&RepoEntry::repo_id) == repo_id ) )); - if (entry) { + if (entry) + { return *entry; } return tl::make_unexpected(api::SeafileException("entry not exists")); } - tl::expected SeafileStore::checkIsUpdated(const std::string &repo_id) { - auto &storage = this->database->storage; + tl::expected SeafileStore::defaultRepoId() const + { + const auto repo = this->api.defaultRepo(this->token,this->token_type); + if (repo) + { + if (repo->exists) + { + return repo->repo_id.value(); + } + return tl::make_unexpected(api::SeafileException("No default repo")); + } + return tl::make_unexpected(api::SeafileException(repo.error())); + } + + tl::expected SeafileStore::checkIsUpdated(const std::string& repo_id) + { + auto& storage = this->database->storage; const auto repo = storage.get_optional( sqlite_orm::where( sqlite_orm::c(&RepoInfo::id) == repo_id )); - if (!repo) { - return true; + if (!repo) + { + return false; } const auto& commit_id = repo.value().head_commit_id; - const auto repo_info = this->api.repoInfo(repo_id,this->token,this->token_type); - if (repo_info) { + const auto repo_info = this->api.repoInfo(repo_id, this->token, this->token_type); + if (repo_info) + { return repo_info.value().head_commit_id == commit_id; } return tl::make_unexpected(repo_info.error()); } + + tl::expected SeafileStore::sync(const std::string& repo_id) const + { + std::stack entry_stack; + std::string path = "/"; + std::vector data; + + entry_stack.push(RepoEntry{.repo_id = repo_id, .path = path}); + + while (!entry_stack.empty()) + { + const auto parent = entry_stack.top(); + entry_stack.pop(); + path = parent.path; + auto entries = this->api.repoDir(repo_id, path, this->token, this->token_type); + if (!entries) + { + return tl::make_unexpected(entries.error()); + } + for (auto& entry : *entries) + { + const auto entry_info = RepoEntry::from_api_model(repo_id, std::format("{}/{}", path, entry.name), + entry); + if (entry_info.type == "dir") + { + entry_stack.push(entry_info); + } + data.push_back(entry_info); + } + }try + { + this->database->storage.transaction([&] + { + for (const auto& entry : data) + { + this->database->storage.insert(entry); + } + return true; + }); + }catch (std::exception& e) + { + return tl::make_unexpected(api::SeafileException(e.what())); + } + return {}; + } + + tl::expected SeafileStore::checkAndSync(const std::string& repo_id) + { + if (!this->checkIsUpdated(repo_id)) + { + return this->sync(repo_id); + } + return {}; + } } diff --git a/src/seafile/fs/storage/repo_entry.cpp b/src/seafile/fs/storage/repo_entry.cpp new file mode 100644 index 0000000..d7071e3 --- /dev/null +++ b/src/seafile/fs/storage/repo_entry.cpp @@ -0,0 +1,31 @@ +// +// Created by Shell on 2026-07-17. +// + +#include "seafile/fs/storage/repo_entry.hpp" + +namespace seafile::fs::storage +{ + auto RepoEntry::from_api_model(const std::string& repo_id, const std::string& path, + const api::RepoEntry& entry) -> RepoEntry + { + return RepoEntry{ + .repo_id = repo_id, + .path = path, + .type = entry.type, + .name = entry.name, + .id = entry.id, + .mtime = entry.mtime, + .modifier_email = entry.modifier_email, + .size = entry.size, + .is_locked = entry.is_locked, + .lock_owner = entry.lock_owner, + .lock_time = entry.lock_time, + .locked_by_me = entry.locked_by_me, + .permission = entry.permission, + .modifier_contact_email = entry.modifier_contact_email, + .modifier_name = entry.modifier_name, + .starred = entry.starred + }; + } +}