#include "dir.h" #include "git.h" #include "repo.h" #include #include #include #include #include #include #include #include #include #include GitFS::Directory::Directory(Repo * const r, std::string && p) : repo(r), path(std::move(p)), 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 e = Git::TreeEntryByPath(repo->tree, path); if (!S_ISDIR(git_tree_entry_filemode(e.get()))) { throw NetFS::SystemError(ENOTDIR); } subTreeCache = Git::TreeLookup(repo->repo, *git_tree_entry_id(e.get())); } subTreeCacheRootId = *git_tree_id(repo->tree.get()); } return subTreeCache; } void GitFS::Directory::close(const ::Ice::Current & current) { current.adapter->remove(current.id); } NetFS::NameList GitFS::Directory::readdir(const ::Ice::Current &) { const auto subTree = getSubtree(); NetFS::NameList list; for (auto idx = git_tree_entrycount(subTree.get()); idx--;) { const auto entry = git_tree_entry_byindex(subTree.get(), idx); list.push_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 a {}; a << *entry << *repo->commit; if (S_ISREG(git_tree_entry_filemode(entry))) { auto blob = Git::BlobLookup(repo->repo, *git_tree_entry_id(entry)); a << *blob; } a.gid = repo->gid; a.uid = repo->uid; list.emplace(git_tree_entry_name(entry), a); } return list; }