File: pathcreateoperation.cpp

package info (click to toggle)
qflipper 1.3.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 12,320 kB
  • sloc: cpp: 18,500; sh: 247; ansic: 191; xml: 38; python: 14; makefile: 5
file content (119 lines) | stat: -rw-r--r-- 3,863 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
#include "pathcreateoperation.h"

#include "flipperzero/protobufsession.h"
#include "flipperzero/rpc/storagestatoperation.h"
#include "flipperzero/rpc/storagemkdiroperation.h"

using namespace Flipper;
using namespace Zero;

PathCreateOperation::PathCreateOperation(ProtobufSession *rpc, DeviceState *deviceState, const QByteArray &remotePath, QObject *parent):
    AbstractUtilityOperation(rpc, deviceState, parent),
    m_remotePath(remotePath),
    m_currentElementIndex(-1),
    m_lastExistingElementIndex(-1)
{}

const QString PathCreateOperation::description() const
{
    return QStringLiteral("Create Path @%1").arg(QString(m_remotePath));
}

bool PathCreateOperation::pathExists() const
{
    return m_lastExistingElementIndex == m_remotePathElements.size();
}

void PathCreateOperation::nextStateLogic()
{
    if(operationState() == Ready) {
        setOperationState(CheckingRootElement);
        checkRootElement();

    } else if(operationState() == CheckingRootElement) {
        setOperationState(CheckingRemotePath);
        checkRemotePath();

    } else if(operationState() == CheckingRemotePath) {
        setOperationState(CreatingRemotePath);
        createRemotePath();

    } else if(operationState() == CreatingRemotePath) {
        finish();

    } else {
        finishWithError(BackendError::UnknownError, QStringLiteral("Unexpected state"));
    }
}

void PathCreateOperation::checkRootElement()
{
    if(!m_remotePath.startsWith('/')) {
        finishWithError(BackendError::UnknownError, QStringLiteral("Path must start with the slash ('/') symbol"));
        return;
    }

    m_remotePathElements = m_remotePath.right(m_remotePath.size() - 1).split('/');

    if(m_remotePathElements.isEmpty()) {
        finishWithError(BackendError::UnknownError, QStringLiteral("Path is empty"));
        return;
    }

    const auto &rootElement = m_remotePathElements.first();

    if((rootElement != QByteArrayLiteral("ext")) && (rootElement != ("int"))) {
        finishWithError(BackendError::UnknownError, QStringLiteral("Invalid remote path: must start with \"int\" or \"ext\""));
    } else if(m_remotePathElements.size() == 1) {
        finish();
    } else {
        m_lastExistingElementIndex = 1;
        advanceOperationState();
    }
}

void PathCreateOperation::checkRemotePath()
{
    const auto currentPath = '/' + m_remotePathElements.mid(0, m_lastExistingElementIndex + 1).join('/');

    auto *operation = rpc()->storageStat(currentPath);

    connect(operation, &AbstractOperation::finished, this, [=]() {
        if(operation->isError()) {
            finishWithError(operation->error(), operation->errorString());
            return;

        } else if(operation->type() == StorageStatOperation::RegularFile) {
            finishWithError(BackendError::UnknownError, QStringLiteral("Remote path %1 is a regular file").arg(QString(currentPath)));
            return;

        } else if(operation->type() == StorageStatOperation::Directory) {
            if(++m_lastExistingElementIndex == m_remotePathElements.size()) {
                finish();
            } else {
                checkRemotePath();
            }

        } else {
            m_currentElementIndex = m_lastExistingElementIndex;
            advanceOperationState();
        }
    });
}

void PathCreateOperation::createRemotePath()
{
    const auto currentPath = '/' + m_remotePathElements.mid(0, m_currentElementIndex + 1).join('/');

    auto *operation = rpc()->storageMkdir(currentPath);

    connect(operation, &AbstractOperation::finished, this, [=]() {
        if(operation->isError()) {
            finishWithError(operation->error(), operation->errorString());
        } else if(++m_currentElementIndex == m_remotePathElements.size()) {
            advanceOperationState();
        } else {
            createRemotePath();
        }
    });
}