Commit 4fb9103b authored by Roland Singer's avatar Roland Singer

first commit

parents
*~
*.pro.user
build
build-debug
Main developers:
Roland Singer <roland@manjaro.org>
This diff is collapsed.
.tableView_orange {
background-color: #FFC34A !important;
}
.tableView_red {
background-color: #FF492F !important;
}
.content {
margin: 10px 10px 10px 10px;
}
.Wt-tableview {
margin: 0 auto;
}
/*
* manjaro-web-repo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backgroundworker.h"
BackgroundWorker::BackgroundWorker()
{
}
BackgroundWorker::~BackgroundWorker()
{
}
void BackgroundWorker::start()
{
m_Thread = boost::thread(&BackgroundWorker::run, this);
}
void BackgroundWorker::run()
{
boost::posix_time::minutes sleepTime(15);
while (true) {
updateRepositoryStateList();
// Sleep
boost::this_thread::sleep(sleepTime);
}
}
void BackgroundWorker::updateRepositoryStateList()
{
QList<Global::RepoState> repoStates;
QMap<QString, QString> currentBranchHashStates;
const QStringList branches = QString(REPO_BRANCHES).split(' ', QString::SkipEmptyParts);
QDateTime currentDateTime = QDateTime::currentDateTime();
/* Get current branch hash state */
for (int i = 0; i < branches.size(); i++) {
const QString branch = branches.at(i);
QFile file(QString(REPO_PATH) + "/" + branch + "/state");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
std::cerr << QString("error: failed to open file '%1'!").arg(file.fileName()).toUtf8().data() << std::endl;
return;
}
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine().split('#', QString::KeepEmptyParts).first().trimmed();
if (!line.startsWith("state") || !line.contains('='))
continue;
currentBranchHashStates[branch] = line.split('=', QString::SkipEmptyParts).last().trimmed();
}
}
/* Get git source */
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
QString tmpPath = QString(TMP_PATH) + "/git";
QStringList args;
if (QDir(tmpPath).exists()) {
process.setWorkingDirectory(tmpPath + "/" + GIT_NAME);
args << "pull" << "origin" << "master";
}
else {
QDir().mkpath(tmpPath);
process.setWorkingDirectory(tmpPath);
args << "clone" << GIT_URL;
}
process.start("git", args);
if (!process.waitForFinished()) {
std::cerr << "error: failed to start git process" << std::endl;
return;
}
if (process.exitCode() != 0) {
std::cerr << "error: git process failed" << std::endl;
std::cerr << "message: " << QString(process.readAll()).toUtf8().data() << std::endl;
return;
}
/* Get mirrors and time */
const QStringList files = QDir(tmpPath + "/" + MIRRORS_PATH).entryList(QDir::Files | QDir::NoDotAndDotDot);
for (int i = 0; i < files.size(); i++) {
const QString filePath = tmpPath + "/" + MIRRORS_PATH + "/" + files.at(i);
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
std::cerr << QString("error: failed to open file '%1'!").arg(filePath).toUtf8().data() << std::endl;
continue;
}
QString country = "unknown";
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine().split('#', QString::KeepEmptyParts).first().trimmed();
if (line.isEmpty())
continue;
if (line.startsWith('[') && line.endsWith(']')) {
country = line.mid(1, line.length() - 2);
}
else if (line.startsWith("Server") && line.contains('=')) {
Global::RepoState repo;
repo.country = country;
repo.url = line.split('=', QString::SkipEmptyParts).last().trimmed();
for (int i = 0; i < branches.size(); i++) {
const QString branch = branches.at(i);
repo.states[branch] = getRepoBranchState(QString(repo.url).replace("$branch/$repo/$arch", branch + "/state"),
currentBranchHashStates.value(branch, ""));
}
repo.url = repo.url.mid(0, repo.url.indexOf("/$branch"));
repo.lastSync = getRepoLastSync(repo.url + "/state", currentDateTime);
if (repo.url.startsWith("http://"))
repo.protocol = "http";
else if (repo.url.startsWith("ftp://"))
repo.protocol = "ftp";
else
repo.protocol = "unknown";
repoStates.append(repo);
}
}
file.close();
}
Global::setRepoStates(repoStates);
}
long BackgroundWorker::getRepoLastSync(const QString & url, const QDateTime & currentDateTime) {
QStringList split = QString::fromStdString(Global::getWebContent(url.toStdString())).split('\n', QString::SkipEmptyParts);
QString repoDateTimeStr;
for (int i = 0; i < split.size(); i++) {
QString line = split.at(i).split('#', QString::KeepEmptyParts).first().trimmed();
if (!line.startsWith("date") || !line.contains('='))
continue;
repoDateTimeStr = line.split('=', QString::SkipEmptyParts).last().trimmed();
}
if (repoDateTimeStr.isEmpty())
return -1;
QDateTime repoDateTime = QDateTime::fromString(repoDateTimeStr, Qt::ISODate);
if (repoDateTime > currentDateTime)
return -1;
return repoDateTime.secsTo(currentDateTime) / 60;
}
Global::STATE BackgroundWorker::getRepoBranchState(const QString & url, const QString & currentBranchHashState)
{
QStringList split = QString::fromStdString(Global::getWebContent(url.toStdString())).split('\n', QString::SkipEmptyParts);
QString hashState;
for (int i = 0; i < split.size(); i++) {
QString line = split.at(i).split('#', QString::KeepEmptyParts).first().trimmed();
if (!line.startsWith("state") || !line.contains('='))
continue;
hashState = line.split('=', QString::SkipEmptyParts).last().trimmed();
}
if (hashState.isEmpty())
return Global::STATE_UNKOWN;
else if (hashState == currentBranchHashState)
return Global::STATE_UP_TO_DATE;
else
return Global::STATE_OUT_OF_DATE;
}
/*
* manjaro-web-repo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BACKGROUNDWORKER_H
#define BACKGROUNDWORKER_H
#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include <QString>
#include <QList>
#include <QMap>
#include "const.h"
#include "global.h"
using namespace Wt;
class BackgroundWorker
{
public:
BackgroundWorker();
~BackgroundWorker();
void start();
private:
boost::thread m_Thread;
void run();
void updateRepositoryStateList();
long getRepoLastSync(const QString & url, const QDateTime & currentDateTime);
Global::STATE getRepoBranchState(const QString & url, const QString & currentBranchHashState);
};
#endif // BACKGROUNDWORKER_H
/*
* manjaro-web-repo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONST_H
#define CONST_H
#define TMP_PATH "/tmp/manjaro-web-repo_tmp"
#define GIT_URL "git://git.manjaro.org/core/pacman-mirrors.git"
#define GIT_NAME "pacman-mirrors"
#define MIRRORS_PATH "pacman-mirrors/data/mirrors"
#define REPO_PATH "/var/repo/repo"
#define REPO_BRANCHES "stable testing unstable"
#endif // CONST_H
/*
* manjaro-web-repo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "global.h"
#include <iostream>
#include <QMutexLocker>
#include <Wt/WStandardItem>
QMutex Global::repoStatesMutex;
QList<Global::RepoState> Global::repoStates;
void Global::init() {
curl_global_init(CURL_GLOBAL_ALL);
}
void Global::cleanup() {
curl_global_cleanup();
}
QList<Global::RepoState> Global::getRepoStates() {
QMutexLocker locker(&repoStatesMutex);
return repoStates;
}
void Global::setRepoStates(const QList<Global::RepoState> & repoStates) {
QMutexLocker locker(&repoStatesMutex);
Global::repoStates.clear();
Global::repoStates = repoStates;
}
std::string Global::getWebContent(const std::string & url)
{
std::ostringstream oss;
if(CURLE_OK == curl_read(url, oss))
return oss.str();
return "";
}
//###
//### Private
//###
size_t Global::data_write(void* buf, size_t size, size_t nmemb, void* userp)
{
if(userp)
{
std::ostream& os = *static_cast<std::ostream*>(userp);
std::streamsize len = size * nmemb;
if(os.write(static_cast<char*>(buf), len))
return len;
}
return 0;
}
CURLcode Global::curl_read(const std::string& url, std::ostream& os, long timeout)
{
CURLcode code(CURLE_FAILED_INIT);
CURL* curl = curl_easy_init();
if(curl)
{
if(CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &data_write))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FILE, &os))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str())))
{
code = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
}
return code;
}
/*
* manjaro-web-repo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GLOBAL_H
#define GLOBAL_H
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <curl/curl.h>
#include <QString>
#include <QList>
#include <QStringList>
#include <QMap>
#include <QProcess>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QMutex>
#include <Wt/WStandardItemModel>
#include "const.h"
using namespace Wt;
class Global
{
public:
enum STATE { STATE_UP_TO_DATE, STATE_OUT_OF_DATE, STATE_UNKOWN };
struct RepoState {
QString url, country, protocol;
long lastSync;
QMap<QString, STATE> states;
};
static void init();
static void cleanup();
static QList<Global::RepoState> getRepoStates();
static void setRepoStates(const QList<Global::RepoState> & repoStates);
static std::string getWebContent(const std::string & url);
private:
static QMutex repoStatesMutex;
static QList<RepoState> repoStates;
static size_t data_write(void* buf, size_t size, size_t nmemb, void* userp);
static CURLcode curl_read(const std::string& url, std::ostream& os, long timeout = 30);
};
#endif // GLOBAL_H
/*
* manjaro-web-repo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <Wt/WApplication>
#include <Wt/WEnvironment>
#include <Wt/WHBoxLayout>
#include <Wt/WBootstrapTheme>
#include <Wt/WCssTheme>
#include "global.h"
#include "mainwidget.h"
#include "backgroundworker.h"
using namespace Wt;
WApplication *createApplication(const WEnvironment& env)
{
Wt::WApplication* app = new Wt::WApplication(env);
if (app->appRoot().empty())
std::cerr << "warning: the approot looks suspect!" << std::endl;
const std::string *theme = env.getParameter("theme");
if (theme)
app->setTheme(new Wt::WCssTheme(*theme));
else
app->setTheme(new Wt::WBootstrapTheme(app));
Wt::WHBoxLayout *layout = new Wt::WHBoxLayout(app->root());
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(new MainWidget());
app->setTitle("Manjaro Linux Repository");
app->useStyleSheet("style/style.css");
return app;
}
int main(int argc, char **argv)
{
// Initialize
Global::init();
// Start our background worker
BackgroundWorker worker;
worker.start();
// Main Application
int ret = WRun(argc, argv, &createApplication);
// Cleanup;
Global::cleanup();
return ret;
}
/*
* ManjaroWebRepo
* Roland Singer <roland@manjaro.org>
*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mainwidget.h"
#include <Wt/WHBoxLayout>
#include <Wt/WMenu>
#include <Wt/WNavigationBar>
#include <Wt/WStackedWidget>
#include <Wt/WText>
#include <Wt/WVBoxLayout>
#include "repositorystatepage.h"