diff --git a/plugin/seafstatus.cpp b/plugin/seafstatus.cpp index cf09a7b..8cd4fa7 100644 --- a/plugin/seafstatus.cpp +++ b/plugin/seafstatus.cpp @@ -3,23 +3,65 @@ #include #include #include +#include extern "C" { #include #include #include #include +#include } +namespace { + +struct ScopedPointerGErrorDeleter +{ + static inline void cleanup(GError *err) { + if (err) + g_error_free(err); + } +}; + +struct ScopedPointerGListDeleter +{ + static inline void cleanup(GList *list) { + if (list) + g_list_free(list); + } +}; + +struct ScopedPointerGObjectDeleter +{ + static inline void cleanup(GObject *obj) { + if (obj) + g_object_unref(obj); + } +}; + +struct ScopedPointerGStringDeleter +{ + static inline void cleanup(char *str) { + if (str) + free(str); + } +}; + +using GListPtr = QScopedPointer; +using GErrorPtr = QScopedPointer; +using GObjectPtr = QScopedPointer; +using GStringPtr = QScopedPointer; + +} + +using namespace std::chrono_literals; + SeafStatus::SeafStatus(QObject *parent) : - QObject(parent), - _client(nullptr), - _repoIds(), - _conTimer(new QTimer(this)) + QObject{parent}, + _conTimer{new QTimer(this)} { _conTimer->setTimerType(Qt::VeryCoarseTimer); - _conTimer->setInterval(60 * 1000);//1 minute - + _conTimer->setInterval(1min); connect(_conTimer, &QTimer::timeout, this, &SeafStatus::freeConnection); } @@ -45,18 +87,17 @@ void SeafStatus::reloadRepos() ensureConnected(); _repoIds.clear(); - GError *error = nullptr; - auto res = seafile_get_repo_list(_client, 0, -1, &error); - if(error) - throw SeafException(error); - else { - for (auto l = res; l != nullptr; l = l->next) { - auto repo = SEAFILE_REPO(l->data); - _repoIds.insert(QString::fromUtf8(seafile_repo_get_worktree(repo)), - QUuid(seafile_repo_get_id(repo))); - } + GError *rawError = nullptr; + GListPtr res {seafile_get_repo_list(_client, 0, -1, &rawError)}; + GErrorPtr error{rawError}; + if (error) + throw SeafException(error.data()); + + for (auto l = res.data(); l != nullptr; l = l->next) { + auto repo = SEAFILE_REPO(l->data); + _repoIds.insert(QString::fromUtf8(seafile_repo_get_worktree(repo)), + QUuid{seafile_repo_get_id(repo)}); } - g_list_free(res); } bool SeafStatus::hasRepo(const QString &path) const @@ -64,7 +105,7 @@ bool SeafStatus::hasRepo(const QString &path) const return _repoIds.contains(repoPath(path)); } -QStringList SeafStatus::allRepost() const +QStringList SeafStatus::allRepos() const { return _repoIds.keys(); } @@ -74,45 +115,44 @@ SeafStatus::SyncStatus SeafStatus::syncStatus(const QString &path) ensureConnected(); auto repo = repoPath(path); - if(!repo.isNull()) { + if (!repo.isNull()) { QDir repoDir{repo}; - auto id = _repoIds.value(repo); - auto idString = id.toByteArray(); - idString = idString.mid(1, idString.size() - 2); - - if(repo == path) { - GError *error = nullptr; - auto taskObj = searpc_client_call__object (_client, "seafile_get_repo_sync_task", SEAFILE_TYPE_SYNC_TASK, - &error, 1, - "string", idString.constData()); - auto task = SEAFILE_SYNC_TASK(taskObj); - if(error) - throw SeafException(error); - else { - if(QByteArray{seafile_sync_task_get_error(task)} != "Success") { - auto msg = QString::fromUtf8(seafile_sync_task_get_err_detail(task)); - g_object_unref(taskObj); - throw SeafException{std::move(msg)}; - } else { - auto status = mapRepoStatus(seafile_sync_task_get_state(task)); - g_object_unref(taskObj); - return status; - } - } + const auto id = _repoIds.value(repo); + const auto idString = id.toByteArray(QUuid::WithoutBraces); + + if (repo == path) { + GError *rawError = nullptr; + GObjectPtr taskObj{searpc_client_call__object(_client, "seafile_get_repo_sync_task", SEAFILE_TYPE_SYNC_TASK, + &rawError, 1, + "string", idString.constData())}; + GErrorPtr error{rawError}; + auto task = SEAFILE_SYNC_TASK(taskObj.data()); + if (error) + throw SeafException(error.data()); + + const auto syncErr = seafile_sync_task_get_error(task); + if (syncErr != SYNC_ERROR_ID_NO_ERROR) { + GStringPtr errStr{searpc_client_call__string(_client, "seafile_sync_error_id_to_str", + &rawError, 1, + "int", syncErr)}; + error.reset(rawError); + if (error) + throw SeafException(error.data()); + throw SeafException{QString::fromUtf8(errStr.data())}; + } else + return mapRepoStatus(seafile_sync_task_get_state(task)); } else { - GError *error = nullptr; - auto res = searpc_client_call__string(_client, "seafile_get_path_sync_status", - &error, 3, - "string", idString.constData(), - "string", repoDir.relativeFilePath(path).toUtf8().constData(), - "int", QFileInfo(path).isDir()); - if(error) - throw SeafException(error); - else { - auto status = mapFileStatus(res); - free(res); - return status; - } + GError *rawError = nullptr; + GStringPtr res{searpc_client_call__string(_client, "seafile_get_path_sync_status", + &rawError, 3, + "string", idString.constData(), + "string", repoDir.relativeFilePath(path).toUtf8().constData(), + "int", QFileInfo{path}.isDir())}; + GErrorPtr error{rawError}; + if (error) + throw SeafException(error.data()); + + return mapFileStatus(res.data()); } } @@ -121,21 +161,20 @@ SeafStatus::SyncStatus SeafStatus::syncStatus(const QString &path) void SeafStatus::ensureConnected() { - if(!_client) { + if (!_client) { // find the socket auto seafDir = readSeafileIni(); - if(seafDir.isNull()) + if (seafDir.isNull()) seafDir = QDir::home().filePath(QStringLiteral("Seafile/.seafile-data")); - auto path = QDir{seafDir}.absoluteFilePath(QStringLiteral("seafile.sock")); + const auto path = QDir{seafDir}.absoluteFilePath(QStringLiteral("seafile.sock")); // create the client auto pipe_client = searpc_create_named_pipe_client(qUtf8Printable(path)); int ret = searpc_named_pipe_client_connect(pipe_client); _client = searpc_client_with_named_pipe_transport(pipe_client, "seafile-rpcserver"); if (ret < 0) { - searpc_free_client_with_pipe_transport(_client); - _client = nullptr; - throw SeafException(tr("Unable to create piped searpc client for seafile-rpcserver")); + freeConnection(); + throw SeafException(tr("Unable to create piped searpc client for seafile-rpcserver")); } reloadRepos(); @@ -154,16 +193,16 @@ void SeafStatus::freeConnection() QString SeafStatus::repoPath(const QString &path) const { - QFileInfo info(path); - auto fullPath = QDir::cleanPath(info.absoluteFilePath()); + const QFileInfo info{path}; + const auto fullPath = QDir::cleanPath(info.absoluteFilePath()); for(auto it = _repoIds.constBegin(); it != _repoIds.constEnd(); it++) { - if(fullPath.startsWith(it.key())) + if (fullPath.startsWith(it.key())) return it.key(); else if(QFileInfo{it.key()}.dir() == QDir{path}) return it.key(); } - return QString(); + return {}; } SeafStatus::SyncStatus SeafStatus::mapFileStatus(const QByteArray &text) const @@ -204,23 +243,23 @@ QString SeafStatus::readSeafileIni() const { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) auto env = qEnvironmentVariable("SEAFILE_DATA_DIR"); - if(!env.isNull()) + if (!env.isNull()) return env; auto ccnetDir = qEnvironmentVariable("CCNET_CONF_DIR"); #else auto env = qgetenv("SEAFILE_DATA_DIR"); - if(!env.isNull()) + if (!env.isNull()) return QString::fromUtf8(env); auto ccnetDir = QString::fromUtf8(qgetenv("CCNET_CONF_DIR")); #endif - if(ccnetDir.isNull()) + if (ccnetDir.isNull()) ccnetDir = QDir::home().filePath(QStringLiteral(".ccnet")); QFile seafile_ini(QDir{ccnetDir}.filePath(QStringLiteral("seafile.ini"))); if (!seafile_ini.exists()) return {}; - if(!seafile_ini.open(QIODevice::ReadOnly | QIODevice::Text)) + if (!seafile_ini.open(QIODevice::ReadOnly | QIODevice::Text)) throw SeafException(tr("%1: %2").arg(seafile_ini.fileName(), seafile_ini.errorString())); QTextStream input(&seafile_ini); @@ -235,9 +274,7 @@ QString SeafStatus::readSeafileIni() const SeafException::SeafException(GError *error) : SeafException(SeafStatus::tr("Seafile Extension: %1").arg(QString::fromUtf8(error->message)).toUtf8()) -{ - g_error_free(error); -} +{} SeafException::SeafException(const QString &message) : QException(), diff --git a/plugin/seafstatus.h b/plugin/seafstatus.h index 75573b1..56f61d7 100644 --- a/plugin/seafstatus.h +++ b/plugin/seafstatus.h @@ -57,7 +57,7 @@ class SeafStatus : public QObject void reloadRepos(); bool hasRepo(const QString &path) const; - QStringList allRepost() const; + QStringList allRepos() const; SyncStatus syncStatus(const QString &path); private slots: @@ -65,7 +65,7 @@ private slots: void freeConnection(); private: - SearpcClient *_client; + SearpcClient *_client = nullptr; QHash _repoIds; QTimer *_conTimer;