#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 + 2); list.emplace_back("."); list.emplace_back(".."); 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; list.emplace(".", list.emplace("..", repo->getdirattr()).first->second); for (auto idx = git_tree_entrycount(subTree.get()); idx--;) { const auto entry = git_tree_entry_byindex(subTree.get(), idx); list.emplace(git_tree_entry_name(entry), repo->getattr(entry)); } return list; }