GitLab: Allow fetching events

Projects that are linked to a GitLab instance will now fetch
notifications for this project and print them to the vcs output pane.

Change-Id: Ifb960e64b30a260327efb28a3dfd26f6457503a0
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2022-05-12 13:54:00 +02:00
parent cd1af2864b
commit dd27901759
8 changed files with 294 additions and 3 deletions

View File

@@ -29,6 +29,8 @@
#include "gitlaboptionspage.h"
#include "gitlabparameters.h"
#include "gitlabprojectsettings.h"
#include "queryrunner.h"
#include "resultparser.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -36,24 +38,39 @@
#include <git/gitplugin.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/session.h>
#include <utils/qtcassert.h>
#include <vcsbase/vcsoutputwindow.h>
#include <QAction>
#include <QMessageBox>
#include <QPointer>
#include <QTimer>
namespace GitLab {
namespace Constants {
const char GITLAB_OPEN_VIEW[] = "GitLab.OpenView";
} // namespace Constants
class GitLabPluginPrivate
class GitLabPluginPrivate : public QObject
{
public:
GitLabParameters parameters;
GitLabOptionsPage optionsPage{&parameters};
QHash<ProjectExplorer::Project *, GitLabProjectSettings *> projectSettings;
QPointer<GitLabDialog> dialog;
QTimer notificationTimer;
QString projectName;
Utils::Id serverId;
bool runningQuery = false;
void setupNotificationTimer();
void fetchEvents();
void fetchUser();
void createAndSendEventsRequest(const QDateTime timeStamp, int page = -1);
void handleUser(const User &user);
void handleEvents(const Events &events, const QDateTime &timeStamp);
};
static GitLabPluginPrivate *dd = nullptr;
@@ -93,6 +110,9 @@ bool GitLabPlugin::initialize(const QStringList & /*arguments*/, QString * /*err
if (dd->dialog)
dd->dialog->updateRemotes();
});
connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged,
this, &GitLabPlugin::onStartupProjectChanged);
return true;
}
@@ -119,6 +139,141 @@ void GitLabPlugin::openView()
dd->dialog->raise();
}
void GitLabPlugin::onStartupProjectChanged()
{
QTC_ASSERT(dd, return);
disconnect(&dd->notificationTimer);
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project) {
dd->notificationTimer.stop();
return;
}
const GitLabProjectSettings *projSettings = projectSettings(project);
if (!projSettings->isLinked()) {
dd->notificationTimer.stop();
return;
}
dd->fetchEvents();
dd->setupNotificationTimer();
}
void GitLabPluginPrivate::setupNotificationTimer()
{
// make interval configurable?
notificationTimer.setInterval(15 * 60 * 1000);
QObject::connect(&notificationTimer, &QTimer::timeout, this, &GitLabPluginPrivate::fetchEvents);
notificationTimer.start();
}
void GitLabPluginPrivate::fetchEvents()
{
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
QTC_ASSERT(project, return);
if (runningQuery)
return;
const GitLabProjectSettings *projSettings = GitLabPlugin::projectSettings(project);
projectName = projSettings->currentProject();
serverId = projSettings->currentServer();
const QDateTime lastRequest = projSettings->lastRequest();
if (!lastRequest.isValid()) { // we haven't queried events for this project yet
fetchUser();
return;
}
createAndSendEventsRequest(lastRequest);
}
void GitLabPluginPrivate::fetchUser()
{
if (runningQuery)
return;
const Query query(Query::User);
QueryRunner *runner = new QueryRunner(query, serverId, this);
QObject::connect(runner, &QueryRunner::resultRetrieved, this, [this](const QByteArray &result) {
handleUser(ResultParser::parseUser(result));
});
QObject::connect(runner, &QueryRunner::finished, [runner]() { runner->deleteLater(); });
runningQuery = true;
runner->start();
}
void GitLabPluginPrivate::createAndSendEventsRequest(const QDateTime timeStamp, int page)
{
if (runningQuery)
return;
Query query(Query::Events, {projectName});
QStringList additional = {"sort=asc"};
QDateTime after = timeStamp.addDays(-1);
additional.append(QLatin1String("after=%1").arg(after.toString("yyyy-MM-dd")));
query.setAdditionalParameters(additional);
if (page > 1)
query.setPageParameter(page);
QueryRunner *runner = new QueryRunner(query, serverId, this);
QObject::connect(runner, &QueryRunner::resultRetrieved, this,
[this, timeStamp](const QByteArray &result) {
handleEvents(ResultParser::parseEvents(result), timeStamp);
});
QObject::connect(runner, &QueryRunner::finished, [runner]() { runner->deleteLater(); });
runningQuery = true;
runner->start();
}
void GitLabPluginPrivate::handleUser(const User &user)
{
runningQuery = false;
QTC_ASSERT(user.error.message.isEmpty(), return);
const QDateTime timeStamp = QDateTime::fromString(user.lastLogin, Qt::ISODateWithMs);
createAndSendEventsRequest(timeStamp);
}
void GitLabPluginPrivate::handleEvents(const Events &events, const QDateTime &timeStamp)
{
runningQuery = false;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
QTC_ASSERT(project, return);
GitLabProjectSettings *projSettings = GitLabPlugin::projectSettings(project);
QTC_ASSERT(projSettings->currentProject() == projectName, return);
if (!projSettings->isLinked()) // link state has changed meanwhile - ignore the request
return;
if (!events.error.message.isEmpty()) {
VcsBase::VcsOutputWindow::appendError("GitLab: Error while fetching events. "
+ events.error.message + '\n');
return;
}
QDateTime lastTimeStamp;
for (const Event &event : events.events) {
const QDateTime eventTimeStamp = QDateTime::fromString(event.timeStamp, Qt::ISODateWithMs);
if (!timeStamp.isValid() || timeStamp < eventTimeStamp) {
VcsBase::VcsOutputWindow::appendMessage("GitLab: " + event.toMessage());
if (!lastTimeStamp.isValid() || lastTimeStamp < eventTimeStamp)
lastTimeStamp = eventTimeStamp;
}
}
if (lastTimeStamp.isValid()) {
if (auto outputWindow = VcsBase::VcsOutputWindow::instance())
outputWindow->flash();
projSettings->setLastRequest(lastTimeStamp);
}
if (events.pageInfo.currentPage < events.pageInfo.totalPages)
createAndSendEventsRequest(timeStamp, events.pageInfo.currentPage + 1);
}
QList<GitLabServer> GitLabPlugin::allGitLabServers()
{
QTC_ASSERT(dd, return {});
@@ -152,4 +307,28 @@ GitLabOptionsPage *GitLabPlugin::optionsPage()
return &dd->optionsPage;
}
void GitLabPlugin::linkedStateChanged(bool enabled)
{
QTC_ASSERT(dd, return);
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (project) {
const GitLabProjectSettings *pSettings = projectSettings(project);
dd->serverId = pSettings->currentServer();
dd->projectName = pSettings->currentProject();
} else {
dd->serverId = Utils::Id();
dd->projectName = QString();
}
if (enabled) {
dd->fetchEvents();
dd->setupNotificationTimer();
} else {
QObject::disconnect(&dd->notificationTimer, &QTimer::timeout,
dd, &GitLabPluginPrivate::fetchEvents);
dd->notificationTimer.stop();
}
}
} // namespace GitLab