File indexing completed on 2024-05-05 17:54:18

0001 // SPDX-FileCopyrightText: 2020 Simon Persson <simon.persson@mykolab.com>
0002 //
0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 
0005 #ifndef BUPVFS_H
0006 #define BUPVFS_H
0007 
0008 #include <QHash>
0009 #include <QObject>
0010 #include <kio/global.h>
0011 #include <sys/types.h>
0012 
0013 #include "vfshelpers.h"
0014 
0015 class Node: public QObject, public Metadata {
0016     Q_OBJECT
0017 public:
0018     Node(QObject *pParent, const QString &pName, qint64 pMode);
0019     ~Node() override {}
0020     virtual int readMetadata(VintStream &pMetadataStream);
0021     Node *resolve(const QString &pPath, bool pFollowLinks = false);
0022     Node *resolve(const QStringList &pPathList, bool pFollowLinks = false);
0023     QString completePath();
0024     Node *parentCommit();
0025 //  Node *parentRepository();
0026     QString mMimeType;
0027 
0028 protected:
0029     static git_revwalk *mRevisionWalker;
0030     static git_repository *mRepository;
0031 };
0032 
0033 typedef QHash<QString, Node*> NodeMap;
0034 typedef QHashIterator<QString, Node*> NodeMapIterator;
0035 
0036 class Directory: public Node {
0037     Q_OBJECT
0038 public:
0039     Directory(QObject *pParent, const QString &pName, qint64 pMode);
0040     ~Directory() override {
0041         delete mSubNodes;
0042     }
0043     virtual NodeMap subNodes();
0044     virtual void reload() {}
0045 
0046 protected:
0047     virtual void generateSubNodes() {}
0048     NodeMap *mSubNodes;
0049 };
0050 
0051 class File: public Node {
0052     Q_OBJECT
0053 public:
0054     File(QObject *pParent, const QString &pName, qint64 pMode)
0055        :Node(pParent, pName, pMode)
0056     {
0057         mOffset = 0;
0058         mCachedSize = 0;
0059     }
0060     virtual quint64 size() {
0061         if(mCachedSize == 0) {
0062             mCachedSize = calculateSize();
0063         }
0064         return mCachedSize;
0065     }
0066     virtual int seek(quint64 pOffset) {
0067         if(pOffset >= size()) {
0068             return KIO::ERR_CANNOT_SEEK;
0069         }
0070         mOffset = pOffset;
0071         return 0; // success
0072     }
0073     virtual int read(QByteArray &pChunk, qint64 pReadSize = -1) = 0;
0074     int readMetadata(VintStream &pMetadataStream) override;
0075 
0076 protected:
0077     virtual quint64 calculateSize() = 0;
0078     quint64 mOffset;
0079     quint64 mCachedSize;
0080 };
0081 
0082 class BlobFile: public File {
0083     Q_OBJECT
0084 public:
0085     BlobFile(Node *pParent, const git_oid *pOid, const QString &pName, qint64 pMode);
0086     ~BlobFile() override;
0087     int read(QByteArray &pChunk, qint64 pReadSize = -1) override;
0088 
0089 protected:
0090     git_blob *cachedBlob();
0091     quint64 calculateSize() override;
0092     git_oid mOid{};
0093     git_blob *mBlob;
0094 };
0095 
0096 class Symlink: public BlobFile {
0097     Q_OBJECT
0098 public:
0099     Symlink(Node *pParent, const git_oid *pOid, const QString &pName, qint64 pMode)
0100        : BlobFile(pParent, pOid, pName, pMode)
0101     {
0102         QByteArray lArray;
0103         if(0 == read(lArray)) {
0104             mSymlinkTarget = QString::fromUtf8(lArray.data(), lArray.size());
0105             Symlink::seek(0);
0106         }
0107     }
0108 };
0109 
0110 class ChunkFile: public File {
0111     Q_OBJECT
0112 public:
0113     ChunkFile(Node *pParent, const git_oid *pOid, const QString &pName, qint64 pMode);
0114     ~ChunkFile() override;
0115     int seek(quint64 pOffset) override;
0116     int read(QByteArray &pChunk, qint64 pReadSize = -1) override;
0117 
0118 protected:
0119     quint64 calculateSize() override;
0120 
0121     git_oid mOid;
0122     git_blob *mCurrentBlob;
0123     struct TreePosition {
0124         explicit TreePosition(git_tree *pTree);
0125         ~TreePosition();
0126         git_tree *mTree;
0127         ulong mIndex;
0128         quint64 mSkipSize;
0129     };
0130 
0131     QList<TreePosition *> mPositionStack;
0132     bool mValidSeekPosition;
0133 };
0134 
0135 class ArchivedDirectory: public Directory {
0136     Q_OBJECT
0137 public:
0138     ArchivedDirectory(Node *pParent, const git_oid *pOid, const QString &pName, qint64 pMode);
0139 
0140 protected:
0141     void generateSubNodes() override;
0142     git_oid mOid{};
0143     git_blob *mMetadataBlob{};
0144     git_tree *mTree;
0145     VintStream *mMetadataStream;
0146 };
0147 
0148 class Branch: public Directory {
0149     Q_OBJECT
0150 public:
0151     Branch(Node *pParent, const char *pName);
0152     void reload() override;
0153 
0154 protected:
0155     void generateSubNodes() override;
0156     QByteArray mRefName;
0157 };
0158 
0159 
0160 class Repository: public Directory {
0161     Q_OBJECT
0162 public:
0163     Repository(QObject *pParent, const QString &pRepositoryPath);
0164     ~Repository() override;
0165     bool isValid() {
0166         return mRepository != nullptr && mRevisionWalker != nullptr;
0167     }
0168 
0169 protected:
0170     void generateSubNodes() override;
0171 };
0172 
0173 
0174 
0175 #endif // BUPVFS_H