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 }