#include "dir.h" #include "git.h" #include "repo.h" #include #include #include #include #include #include #include #include #include #include GitFS::Directory::Directory(Repo * const repo, std::string path) : repo(repo), path(std::move(path)), subTreeCacheRootId({}) { getSubtree(); } GitFS::Git::TreePtr GitFS::Directory::getSubtree() const { repo->update(); if (!git_oid_equal(&subTreeCacheRootId, git_tree_id(repo->tree.get()))) { if (path == "/") { subTreeCache = repo->tree; } else { auto entry = Git::treeEntryByPath(repo->tree, path); if (!S_ISDIR(git_tree_entry_filemode(entry.get()))) { throw NetFS::SystemError(ENOTDIR); } subTreeCache = Git::treeLookup(repo->repo, *git_tree_entry_id(entry.get())); } subTreeCacheRootId = *git_tree_id(repo->tree.get()); } return subTreeCache; } void GitFS::Directory::close(const ::Ice::Current & ice) { ice.adapter->remove(ice.id); } NetFS::NameList GitFS::Directory::readdir(const ::Ice::Current &) { const auto subTree = getSubtree(); NetFS::NameList list; auto idx = git_tree_entrycount(subTree.get()); list.reserve(idx); while (idx--) { const auto entry = git_tree_entry_byindex(subTree.get(), idx); list.emplace_back(git_tree_entry_name(entry)); } return list; } NetFS::DirectoryContents GitFS::Directory::listdir(const ::Ice::Current &) { const auto subTree = getSubtree(); NetFS::DirectoryContents list; for (auto idx = git_tree_entrycount(subTree.get()); idx--;) { const auto entry = git_tree_entry_byindex(subTree.get(), idx); NetFS::Attr attr {}; attr << *entry << *repo->commit; if (S_ISREG(git_tree_entry_filemode(entry))) { auto blob = Git::blobLookup(repo->repo, *git_tree_entry_id(entry)); attr << *blob; } attr.gid = repo->gid; attr.uid = repo->uid; list.emplace(git_tree_entry_name(entry), std::move(attr)); } return list; }