From f23c6a3fbb24932c7f0d49b430c363f4559cb24d Mon Sep 17 00:00:00 2001 From: asypost Date: Wed, 22 Jul 2026 22:00:04 +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_store.hpp | 4 +- src/main.cpp | 8 ++ src/seafile/fs/seafile_store.cpp | 178 +++++++++++++++++++-------- 4 files changed, 142 insertions(+), 49 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6523aaa..93160a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ add_executable(seadisk src/main.cpp src/seafile/fs/storage/repo_entry.cpp include/seafile/util/version.hpp src/seafile/util/version.cpp + src/util/application_path.cpp ) target_compile_definitions(seadisk PRIVATE diff --git a/include/seafile/fs/seafile_store.hpp b/include/seafile/fs/seafile_store.hpp index 044cf37..4b4342e 100644 --- a/include/seafile/fs/seafile_store.hpp +++ b/include/seafile/fs/seafile_store.hpp @@ -24,6 +24,8 @@ namespace seafile::fs SeafileStore(const SeafileStore&) = delete; + ~SeafileStore(); + tl::expected auth(); [[nodiscard]] tl::expected defaultRepoId() const; @@ -50,7 +52,7 @@ namespace seafile::fs /// 同步 tl::expected sync(); - std::filesystem::path storePath() const; + static std::filesystem::path storePath() ; /// 获取路径信息 diff --git a/src/main.cpp b/src/main.cpp index 837abae..419a8a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,6 @@ #include + +#include "seafile/fs/seafile_store.hpp" #include "seafile/fs/winfsp_adapter.hpp" using namespace seafile::fs; @@ -9,6 +11,12 @@ auto wmain(int argc, wchar_t** argv) -> int return ERROR_DELAY_LOAD_FAILED; FspDebugLogSetHandle(GetStdHandle(STD_ERROR_HANDLE)); + SeafileStore store{SeafileStore::storePath().string(),"https://pan.hanwangsoft.com","asypost@yeah.net","Shell0805@china"}; + const auto result = store.init(); + if (!result) + { + std::wcout << result.error().what() << std::endl; + } return FspServiceRun(const_cast(L"SeaDisk"), WinFSPAdapter::SvcStart, WinFSPAdapter::SvcStop, nullptr); } diff --git a/src/seafile/fs/seafile_store.cpp b/src/seafile/fs/seafile_store.cpp index 4e9c02c..76aea14 100644 --- a/src/seafile/fs/seafile_store.cpp +++ b/src/seafile/fs/seafile_store.cpp @@ -12,23 +12,26 @@ // // 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", sqlite_orm::make_column("space_usage", &AccountInfo::space_usage), sqlite_orm::make_column("avatar_url", &AccountInfo::avatar_url), - sqlite_orm::make_column("email", &AccountInfo::email), + sqlite_orm::make_column("email", &AccountInfo::email, sqlite_orm::primary_key()), sqlite_orm::make_column("name", &AccountInfo::name), sqlite_orm::make_column("total", &AccountInfo::total), sqlite_orm::make_column("usage", &AccountInfo::usage), - sqlite_orm::make_column("login_id", &AccountInfo::login_id,sqlite_orm::primary_key()), + sqlite_orm::make_column("login_id", &AccountInfo::login_id), sqlite_orm::make_column("department", &AccountInfo::department), sqlite_orm::make_column("contact_email", &AccountInfo::contact_email), sqlite_orm::make_column("institution", &AccountInfo::institution), @@ -38,7 +41,7 @@ namespace seafile::fs { ), sqlite_orm::make_table("repo_info", sqlite_orm::make_column("type",&RepoInfo::type), - sqlite_orm::make_column("id",&RepoInfo::id), + sqlite_orm::make_column("id",&RepoInfo::id, sqlite_orm::primary_key()), sqlite_orm::make_column("owner",&RepoInfo::owner), sqlite_orm::make_column("name",&RepoInfo::name), sqlite_orm::make_column("mtime",&RepoInfo::mtime), @@ -60,7 +63,7 @@ namespace seafile::fs { sqlite_orm::make_column("type",&RepoEntry::type), sqlite_orm::make_column("name",&RepoEntry::name), sqlite_orm::make_column("path",&RepoEntry::path), - sqlite_orm::make_column("id",&RepoEntry::id), + sqlite_orm::make_column("id", &RepoEntry::id, sqlite_orm::primary_key()), sqlite_orm::make_column("mtime",&RepoEntry::mtime), sqlite_orm::make_column("modifier_email",&RepoEntry::modifier_email), sqlite_orm::make_column("size",&RepoEntry::size), @@ -77,25 +80,32 @@ 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)) + { } }; - tl::expected SeafileStore::auth() { - if (const auto auth_info = this->api.auth(this->username, this->password)) { + tl::expected SeafileStore::auth() + { + if (const auto auth_info = this->api.auth(this->username, this->password)) + { return {}; - } else { + } + 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) { + 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->username = user; this->password = password; @@ -103,8 +113,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_( @@ -112,16 +123,20 @@ 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::defaultRepoId() const { + tl::expected SeafileStore::defaultRepoId() const + { const auto repo = this->api.defaultRepo(); - if (repo) { - if (repo->exists) { + if (repo) + { + if (repo->exists) + { return repo->repo_id.value(); } return tl::make_unexpected(api::SeafileException("No default repo")); @@ -129,90 +144,157 @@ namespace seafile::fs { return tl::make_unexpected(api::SeafileException(repo.error())); } - tl::expected SeafileStore::checkIsUpdated(const std::string &repo_id) { - auto &storage = this->database->storage; + 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) { + if (!repo) + { return false; } - const auto &commit_id = repo.value().head_commit_id; + const auto& commit_id = repo.value().head_commit_id; const auto repo_info = this->api.repoInfo(repo_id); - if (repo_info) { + if (repo_info) + { return repo_info.value().head_commit_id == commit_id; } return tl::make_unexpected(repo_info.error()); } - tl::expected SeafileStore::syncRepoEntry(const std::string &repo_id) const { + tl::expected SeafileStore::syncRepoEntry(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()) { + while (!entry_stack.empty()) + { const auto parent = entry_stack.top(); entry_stack.pop(); path = parent.path; auto entries = this->api.repoDir(repo_id, path); - if (!entries) { + if (!entries) + { return tl::make_unexpected(entries.error()); } - for (auto &entry: *entries) { + 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") { + 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); + try + { + this->database->storage.transaction([&] + { + for (const auto& entry : data) + { + this->database->storage.replace(entry); } return true; }); - } catch (std::exception &e) { + } + 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)) { + tl::expected SeafileStore::checkAndSync(const std::string& repo_id) + { + if (!this->checkIsUpdated(repo_id)) + { return this->syncRepoEntry(repo_id); } return {}; } - tl::expected SeafileStore::init() { - if (const auto &store_path = this->storePath(); !std::filesystem::exists(store_path)) { - this->database->storage.sync_schema(); - return this->sync(); + tl::expected SeafileStore::init() + { + if (const auto& store_path = storePath(); !std::filesystem::exists(store_path)) + { + try + { + this->database->storage.sync_schema(); + } + catch (std::exception& e) + { + return tl::make_unexpected(api::SeafileException(e.what())); + } } - return {}; + const auto auth_token = this->auth(); + if (!auth_token) + { + return tl::make_unexpected(auth_token.error()); + } + return this->sync();; } - tl::expected SeafileStore::syncUserInfo() { + tl::expected SeafileStore::syncUserInfo() + { const auto user_info = this->api.accountInfo(); - if (!user_info) { + if (!user_info) + { return tl::make_unexpected(user_info.error()); } this->database->storage.replace(*user_info); return {}; } - tl::expected SeafileStore::syncRepos() { + tl::expected SeafileStore::syncRepos() + { + const auto repos = this->api.repos("mine", ""); + if (!repos) + { + return tl::make_unexpected(repos.error()); + } + for (const auto& repo : *repos) + { + try + { + this->database->storage.replace(repo); + } + catch (std::exception& e) + { + return tl::make_unexpected(api::SeafileException(e.what())); + } + if (const auto sync_repo = syncRepoEntry(repo.id); !sync_repo) + { + return tl::make_unexpected(sync_repo.error()); + } + } return {}; } - std::filesystem::path SeafileStore::storePath() const { - return shell::util::ApplicationPath::get() / "seafile.sqlite"; + tl::expected SeafileStore::sync() + { + if (const auto sync_account = this->syncUserInfo(); !sync_account) + { + return tl::make_unexpected(sync_account.error()); + } + if (const auto sync_repos = syncRepos(); !sync_repos) + { + return tl::make_unexpected(sync_repos.error()); + } + return {}; + } + + SeafileStore::~SeafileStore() = default; + + std::filesystem::path SeafileStore::storePath() + { + return shell::util::ApplicationPath::get().parent_path() / "seafile.sqlite"; } }