File indexing completed on 2025-03-09 05:11:41

0001 /*
0002 SPDX-FileCopyrightText: 2021 Hamed Masafi <hamed.masfi@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-3.0-or-later
0005 */
0006 
0007 #include "tree.h"
0008 #include "qdebug.h"
0009 #include "types.h"
0010 #include <git2/commit.h>
0011 #include <git2/tree.h>
0012 
0013 namespace Git
0014 {
0015 
0016 Tree::Tree(git_tree *tree)
0017     : ptr{tree}
0018 {
0019     initTree();
0020 }
0021 
0022 Tree::~Tree()
0023 {
0024     if (ptr)
0025         git_tree_free(ptr);
0026 }
0027 
0028 QList<Tree::Entry> Tree::entries(const QString &path) const
0029 {
0030     return mTreeData.values(path);
0031 }
0032 
0033 QStringList Tree::entries(const QString &path, EntryType filter) const
0034 {
0035     auto entries = this->entries(path);
0036     QStringList ret;
0037     for (auto &en : entries)
0038         if (filter == EntryType::All || en.type == filter)
0039             ret << en.name;
0040     return ret;
0041 }
0042 
0043 QSharedPointer<File> Tree::file(const QString &path)
0044 {
0045     git_tree_entry *entry;
0046     BEGIN
0047     STEP git_tree_entry_bypath(&entry, ptr, toConstChars(path));
0048 
0049     if (err)
0050         return {};
0051 
0052     return QSharedPointer<File>{new File{git_tree_owner(ptr), entry}};
0053 }
0054 
0055 git_tree *Tree::gitTree() const
0056 {
0057     return ptr;
0058 }
0059 
0060 void Tree::initTree()
0061 {
0062     auto cb = [](const char *root, const git_tree_entry *entry, void *payload) -> int {
0063         auto w = reinterpret_cast<Tree *>(payload);
0064         QString path{root};
0065         QString name{git_tree_entry_name(entry)};
0066 
0067         if (path.endsWith("/"))
0068             path = path.mid(0, path.length() - 1);
0069 
0070         auto type = git_tree_entry_type(entry);
0071         switch (type) {
0072         case GIT_OBJECT_BLOB:
0073             w->mTreeData.insert(path, Entry{name, EntryType::File});
0074             break;
0075         case GIT_OBJECT_TREE:
0076             w->mTreeData.insert(path, Entry{name, EntryType::Dir});
0077             break;
0078         case GIT_OBJECT_COMMIT:
0079         case GIT_OBJECT_ANY:
0080         case GIT_OBJECT_INVALID:
0081         case GIT_OBJECT_TAG:
0082         case GIT_OBJECT_OFS_DELTA:
0083         case GIT_OBJECT_REF_DELTA:
0084             break;
0085         }
0086         return 0;
0087     };
0088 
0089     git_tree_walk(ptr, GIT_TREEWALK_PRE, cb, this);
0090 }
0091 
0092 }
0093 
0094 Git::Tree::EntryType QListSpecialMethods<Git::Tree::Entry>::type(const QString &entryName) const
0095 {
0096     auto self = static_cast<QList<Git::Tree::Entry> *>(const_cast<QListSpecialMethods<Git::Tree::Entry> *>(this));
0097 
0098     auto i = std::find_if(self->begin(), self->end(), [&entryName](Git::Tree::Entry en) {
0099         return en.name == entryName;
0100     });
0101 
0102     if (i == self->end())
0103         return Git::Tree::EntryType::Unknown;
0104 
0105     return (*i).type;
0106 }
0107 
0108 QDebug operator<<(QDebug d, const QList<Git::Tree::Entry> &list)
0109 {
0110     bool first{true};
0111 
0112     auto &dd = d.noquote().nospace();
0113 
0114     for (auto &entry : list) {
0115         if (!first)
0116             dd << ", ";
0117 
0118         dd << "(" << entry.name << ": ";
0119 
0120         switch (entry.type) {
0121         case Git::Tree::EntryType::Unknown:
0122             dd << "Unknown";
0123             break;
0124         case Git::Tree::EntryType::File:
0125             dd << "File";
0126             break;
0127         case Git::Tree::EntryType::Dir:
0128             dd << "Dir";
0129             break;
0130         }
0131         dd << ")";
0132         first = false;
0133     }
0134 
0135     return dd;
0136 }
0137 
0138 bool QListSpecialMethods<Git::Tree::Entry>::contains(const QString &entryName) const
0139 {
0140     auto self = static_cast<QList<Git::Tree::Entry> *>(const_cast<QListSpecialMethods<Git::Tree::Entry> *>(this));
0141 
0142     return std::any_of(self->begin(), self->end(), [&entryName](Git::Tree::Entry en) {
0143         return en.name == entryName;
0144     });
0145 }
0146 
0147 qsizetype QListSpecialMethods<Git::Tree::Entry>::indexOf(const QString &entryName, qsizetype from) const
0148 {
0149     auto self = static_cast<QList<Git::Tree::Entry> *>(const_cast<QListSpecialMethods<Git::Tree::Entry> *>(this));
0150 
0151     for (qsizetype i = 0; i < self->size(); ++i) {
0152         if (self->at(i).name == entryName) {
0153             return i;
0154         }
0155     }
0156 
0157     return -1;
0158 }
0159 
0160 qsizetype QListSpecialMethods<Git::Tree::Entry>::lastIndexOf(const QString &entryName, qsizetype from) const
0161 {
0162     auto self = static_cast<QList<Git::Tree::Entry> *>(const_cast<QListSpecialMethods<Git::Tree::Entry> *>(this));
0163 
0164     auto startIndex = from;
0165     if (startIndex == -1) {
0166         startIndex = self->size();
0167     }
0168 
0169     for (qsizetype i = startIndex; i > 0; --i) {
0170         if (self->at(i).name == entryName) {
0171             return i;
0172         }
0173     }
0174 
0175     return -1;
0176 }