File: purger.cpp

package info (click to toggle)
kup-backup 0.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,576 kB
  • sloc: cpp: 8,422; xml: 311; makefile: 6; sh: 3
file content (148 lines) | stat: -rw-r--r-- 6,084 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// SPDX-FileCopyrightText: 2021 Simon Persson <simon.persson@mykolab.com>
//
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL

#include "purger.h"
#include "kuppurger_debug.h"

#include <KFormat>
#include <KLocalizedString>
#include <KStandardAction>
#include <KToolBar>

#include <QDateTime>
#include <QGuiApplication>
#include <QHash>
#include <QSplitter>

Purger::Purger(QString pRepoPath, QString pBranchName, QWidget *pParent)
    : KMainWindow(pParent)
    , mRepoPath(std::move(pRepoPath))
    , mBranchName(std::move(pBranchName))
{
    setWindowIcon(QIcon::fromTheme(QStringLiteral("kup")));
    KToolBar *lAppToolBar = toolBar();
    lAppToolBar->addAction(KStandardAction::quit(this, SLOT(close()), this));
    mDeleteAction = KStandardAction::deleteFile(this, SLOT(purge()), this);
    lAppToolBar->addAction(mDeleteAction);

    mListWidget = new QListWidget();
    auto lSplitter = new QSplitter();
    lSplitter->addWidget(mListWidget);
    mTextEdit = new QTextEdit();
    mTextEdit->setReadOnly(true);
    lSplitter->addWidget(mTextEdit);
    setCentralWidget(lSplitter);

    mCollectProcess = new KProcess();
    mCollectProcess->setOutputChannelMode(KProcess::SeparateChannels);
    *mCollectProcess << QStringLiteral("bup");
    *mCollectProcess << QStringLiteral("-d") << mRepoPath;
    *mCollectProcess << QStringLiteral("gc") << QStringLiteral("--unsafe") << QStringLiteral("--verbose");
    connect(mCollectProcess, &KProcess::readyReadStandardError, this, [this] {
        auto lLogText = QString::fromUtf8(mCollectProcess->readAllStandardError());
        qCInfo(KUPPURGER) << lLogText;
        mTextEdit->append(lLogText);
    });
    connect(mCollectProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &Purger::purgeDone);

    mListProcess = new KProcess();
    mListProcess->setOutputChannelMode(KProcess::SeparateChannels);
    *mListProcess << QStringLiteral("bup");
    *mListProcess << QStringLiteral("-d") << mRepoPath;
    *mListProcess << QStringLiteral("ls") << QStringLiteral("--hash") << mBranchName;
    connect(mListProcess, &KProcess::readyReadStandardOutput, this, [this] {
        KFormat lFormat;
        const auto lLines = QString::fromUtf8(mListProcess->readAllStandardOutput()).split(QChar::LineFeed);
        for (const QString &lLine : lLines) {
            qCDebug(KUPPURGER) << lLine;
            const auto lHash = lLine.left(40);
            if (!lHash.isEmpty() && lHash != QStringLiteral("0000000000000000000000000000000000000000")) {
                const auto lTimeStamp = lLine.mid(41);
                if (mHashes.contains(lHash)) {
                    auto lItem = mHashes.value(lHash);
                    lItem->setWhatsThis(lItem->whatsThis() + QChar::LineFeed + lTimeStamp);
                } else {
                    const auto lDateTime = QDateTime::fromString(lTimeStamp, QStringLiteral("yyyy-MM-dd-HHmmss"));
                    const auto lDisplayText = lFormat.formatRelativeDateTime(lDateTime, QLocale::ShortFormat);
                    auto lItem = new QListWidgetItem(lDisplayText, mListWidget);
                    lItem->setWhatsThis(lTimeStamp); // misuse of field, for later use when removing
                    lItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
                    lItem->setCheckState(Qt::Unchecked);
                    mHashes.insert(lHash, lItem);
                }
            }
        }
    });
    connect(mListProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &Purger::listDone);

    fillListWidget();
}

QSize Purger::sizeHint() const
{
    return {800, 600};
}

void Purger::fillListWidget()
{
    QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    mListWidget->clear();
    mHashes.clear();
    mDeleteAction->setEnabled(false);
    mListProcess->start();
}

void Purger::listDone(int, QProcess::ExitStatus)
{
    QGuiApplication::restoreOverrideCursor();
    mDeleteAction->setEnabled(true);
}

void Purger::purge()
{
    qCInfo(KUPPURGER) << "Starting purge operation.";
    mDeleteAction->setEnabled(false);
    bool lAnythingRemoved = false;
    for (int i = 0; i < mListWidget->count(); ++i) {
        auto lItem = mListWidget->item(i);
        qCInfo(KUPPURGER) << lItem->text() << lItem->whatsThis() << lItem->checkState();
        if (lItem->checkState() == Qt::Checked) {
            const auto lTimeStamps = lItem->whatsThis().split(QChar::LineFeed);
            for (const QString &lTimeStamp : lTimeStamps) {
                KProcess lRemoveProcess;
                lRemoveProcess.setOutputChannelMode(KProcess::SeparateChannels);
                lRemoveProcess << QStringLiteral("bup");
                lRemoveProcess << QStringLiteral("-d") << mRepoPath << QStringLiteral("rm");
                lRemoveProcess << QStringLiteral("--unsafe") << QStringLiteral("--verbose");
                lRemoveProcess << QString("%1/%2").arg(mBranchName, lTimeStamp);
                qCInfo(KUPPURGER) << lRemoveProcess.program();
                if (lRemoveProcess.execute() == 0) {
                    lAnythingRemoved = true;
                    qCInfo(KUPPURGER) << "Successfully removed snapshot";
                }
                const auto lLogText = QString::fromUtf8(lRemoveProcess.readAllStandardError());
                qCInfo(KUPPURGER) << lLogText;
                mTextEdit->append(lLogText);
            }
        }
    }
    if (lAnythingRemoved) {
        QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
        qCInfo(KUPPURGER) << mCollectProcess->program();
        mCollectProcess->start();
    } else {
        mDeleteAction->setEnabled(true);
    }
}

void Purger::purgeDone(int pExitCode, QProcess::ExitStatus pExitStatus)
{
    qCInfo(KUPPURGER) << pExitCode << pExitStatus;
    QGuiApplication::restoreOverrideCursor();
    mDeleteAction->setEnabled(true);
    const auto lLogText = QString::fromUtf8(mCollectProcess->readAllStandardError());
    qCInfo(KUPPURGER) << lLogText;
    mTextEdit->append(lLogText);
    fillListWidget();
}