添加本地存储

This commit is contained in:
shell committed 2026-07-16 23:55:29 +08:00
1 parent 95b68b9542
commit e8b91b1a59
5 files changed
+255

No files matched your search

+6
View File
@@ -11,6 +11,7 @@ find_package(argparse CONFIG REQUIRED)
find_package(ada CONFIG REQUIRED) find_package(ada CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED) find_package(spdlog CONFIG REQUIRED)
find_package(ICU REQUIRED COMPONENTS uc i18n) find_package(ICU REQUIRED COMPONENTS uc i18n)
find_package(SqliteOrm CONFIG REQUIRED)
cmake_host_system_information( cmake_host_system_information(
RESULT WINFSP_DIR RESULT WINFSP_DIR
@@ -58,6 +59,10 @@ add_executable(seadisk src/main.cpp
include/seafile/api/seafile_api_interface.hpp include/seafile/api/seafile_api_interface.hpp
include/seafile/api/seafile_api_interface.hpp include/seafile/api/seafile_api_interface.hpp
include/seafile/api/cached_seafile_api.hpp include/seafile/api/cached_seafile_api.hpp
include/seafile/fs/seafile_store.hpp
include/seafile/fs/seafile_store.hpp
src/seafile/fs/seafile_store.cpp
include/seafile/fs/storage/repo_entry.hpp
) )
target_compile_definitions(seadisk PRIVATE target_compile_definitions(seadisk PRIVATE
@@ -88,6 +93,7 @@ target_link_libraries(seadisk PRIVATE
spdlog::spdlog spdlog::spdlog
ICU::uc ICU::uc
ICU::i18n ICU::i18n
sqlite_orm::sqlite_orm
) )
target_link_options(seadisk PRIVATE target_link_options(seadisk PRIVATE
+57
View File
@@ -0,0 +1,57 @@
//
// Created by Shell on 2026/7/16.
//
#ifndef SEADISK_SEAFILE_STORE_HPP
#define SEADISK_SEAFILE_STORE_HPP
#include "seafile/api/seafile_api.hpp"
#include <sqlite_orm/sqlite_orm.h>
#include "storage/repo_entry.hpp"
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 SeafileStore &) = default;
tl::expected<void,api::SeafileException> auth();
/// 检查是否已经更新到最新
/// @return true 已经最新,false 需要更新
tl::expected<bool, api::SeafileException> checkIsUpdated(const std::string& repo_id);
/// 检查是否需要更新元素据,如果需要同步则自动同步
tl::expected<void, api::SeafileException> checkAndSync(const std::string& repo_id,);
/// 同步元数据
tl::expected<void, api::SeafileException> sync(const std::string& repo_id);
/// 获取路径信息
/// @param path 路径
/// @return 路径信息
tl::expected<storage::RepoEntry, api::SeafileException> findRepoEntry(const std::string& repo_id, const std::string &path);
private:
struct Database;
std::unique_ptr<Database> database;
std::string api_server;
std::string user;
std::string password;
std::string token;
api::TokenType token_type = api::TokenType::TOKEN;
api::SeaFileApi api;
};
}
#endif //SEADISK_SEAFILE_STORE_HPP
+61
View File
@@ -0,0 +1,61 @@
//
// Created by Shell on 2026/7/16.
//
#ifndef SEADISK_STORAGE_REPO_ENTRY_HPP
#define SEADISK_STORAGE_REPO_ENTRY_HPP
#include "seafile/api/repo_entry.hpp"
#include <string>
namespace seafile::fs::storage {
struct RepoEntry final {
///repo id
std::string repo_id;
///entry path
std::string path;
/// Entry type ("file" or "dir").
std::string type;
/// File or directory name.
std::string name;
/// Object identifier.
std::string id;
/// Last modification time (Unix timestamp, seconds).
std::int64_t mtime{};
/// Internal email address of the last modifier.
std::optional<std::string> modifier_email;
/// File size in bytes. For directories this may be 0.
std::optional<std::uint64_t> size{};
/// Whether the file is currently locked.
std::optional<bool> is_locked{};
/// Lock owner email or identifier. Null if unlocked.
std::optional<std::string> lock_owner;
/// Lock timestamp (Unix timestamp, seconds).
std::optional<std::int64_t> lock_time{};
/// Whether the current user owns the lock.
std::optional<bool> locked_by_me{};
/// Current user's permission (e.g. "r", "rw").
std::optional<std::string> permission;
/// Contact email address of the last modifier.
std::optional<std::string> modifier_contact_email;
/// Display name of the last modifier.
std::optional<std::string> modifier_name;
/// Whether the entry is starred by the current user.
std::optional<bool> starred{};
};
}
#endif //SEADISK_STORAGE_REPO_ENTRY_HPP
+128
View File
@@ -0,0 +1,128 @@
#include "seafile/fs/seafile_store.hpp"
#include <sqlite_orm/sqlite_orm.h>
#include <string>
#include "seafile/api/account_info.hpp"
#include "seafile/api/repo_info.hpp"
#include "seafile/fs/storage/repo_entry.hpp"
//
// Created by Shell on 2026/7/16.
//
namespace seafile::fs {
using RepoEntry = storage::RepoEntry;
using AccountInfo = api::AccountInfo;
using RepoInfo = api::RepoInfo;
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("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::make_column("department", &AccountInfo::department),
sqlite_orm::make_column("contact_email", &AccountInfo::contact_email),
sqlite_orm::make_column("institution", &AccountInfo::institution),
sqlite_orm::make_column("is_staff", &AccountInfo::is_staff),
sqlite_orm::make_column("file_updates_email_interval", &AccountInfo::file_updates_email_interval),
sqlite_orm::make_column("collaborate_email_interval",&AccountInfo::collaborate_email_interval)
),
sqlite_orm::make_table("repo_info",
sqlite_orm::make_column("type",&RepoInfo::type),
sqlite_orm::make_column("id",&RepoInfo::id),
sqlite_orm::make_column("owner",&RepoInfo::owner),
sqlite_orm::make_column("name",&RepoInfo::name),
sqlite_orm::make_column("mtime",&RepoInfo::mtime),
sqlite_orm::make_column("size",&RepoInfo::size),
sqlite_orm::make_column("encrypted",&RepoInfo::encrypted),
sqlite_orm::make_column("root",&RepoInfo::root),
sqlite_orm::make_column("permission",&RepoInfo::permission),
sqlite_orm::make_column("modifier_email",&RepoInfo::modifier_email),
sqlite_orm::make_column("modifier_contact_email",&RepoInfo::modifier_contact_email),
sqlite_orm::make_column("modifier_name",&RepoInfo::modifier_name),
sqlite_orm::make_column("file_count",&RepoInfo::file_count),
sqlite_orm::make_column("head_commit_id",&RepoInfo::head_commit_id),
sqlite_orm::make_column("enc_version",&RepoInfo::enc_version),
sqlite_orm::make_column("salt",&RepoInfo::salt),
sqlite_orm::make_column("magic",&RepoInfo::magic),
sqlite_orm::make_column("random_key",&RepoInfo::random_key)
),
sqlite_orm::make_table("repo_entry",
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("mtime",&RepoEntry::mtime),
sqlite_orm::make_column("modifier_email",&RepoEntry::modifier_email),
sqlite_orm::make_column("size",&RepoEntry::size),
sqlite_orm::make_column("is_locked",&RepoEntry::is_locked),
sqlite_orm::make_column("lock_owner",&RepoEntry::lock_owner),
sqlite_orm::make_column("lock_time",&RepoEntry::lock_time),
sqlite_orm::make_column("locked_by_me",&RepoEntry::locked_by_me),
sqlite_orm::make_column("permission",&RepoEntry::permission),
sqlite_orm::make_column("modifier_contact_email",&RepoEntry::modifier_contact_email),
sqlite_orm::make_column("modifier_name",&RepoEntry::modifier_name),
sqlite_orm::make_column("starred",&RepoEntry::starred))
);
//clang-format on
}
}
struct SeafileStore::Database {
using Storage = decltype(make_storage(""));
Storage storage;
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) {
this->database = std::make_unique<Database>(db_path);
this->user = user;
this->password = password;
this->api_server = server;
}
tl::expected<RepoEntry, api::SeafileException> SeafileStore::findRepoEntry(
const std::string &repo_id, const std::string &path) {
auto &storage = this->database->storage;
const auto entry = storage.get_optional<RepoEntry>(
sqlite_orm::where(
sqlite_orm::and_(
sqlite_orm::c(&RepoEntry::path) == path,
sqlite_orm::c(&RepoEntry::repo_id) == repo_id
)
));
if (entry) {
return *entry;
}
return tl::make_unexpected(api::SeafileException("entry not exists"));
}
tl::expected<bool, api::SeafileException> SeafileStore::checkIsUpdated(const std::string &repo_id) {
auto &storage = this->database->storage;
const auto repo = storage.get_optional<RepoInfo>(
sqlite_orm::where(
sqlite_orm::c(&RepoInfo::id) == repo_id
));
if (!repo) {
return true;
}
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) {
return repo_info.value().head_commit_id == commit_id;
}
return tl::make_unexpected(repo_info.error());
}
}
+3
View File
@@ -27,5 +27,8 @@
}, { }, {
"name" : "spdlog", "name" : "spdlog",
"version>=" : "1.17.0" "version>=" : "1.17.0"
}, {
"name" : "sqlite-orm",
"version>=" : "1.9.1"
} ] } ]
} }