#include "repo.h" #include "blob.h" #include "dir.h" #include #include #include #include #include #include #include #include #include #include #include #include #include std::string operator/(const std::string & a, const std::string & b) { return a.empty() ? b : a; } GitFS::Repo::Repo(const PropertyReader & properties) : repo(Git::RepositoryOpenBare(properties("gitdir"))), commitish(properties("commitish") / "master"), isBranch(false), resolvedAt(0), gid(properties("gid") / "root"), uid(properties("uid") / "root") { if (commitish.length() == GIT_OID_HEXSZ) { commit = Git::CommitLookup(repo, Git::OidParse(commitish)); } else { ref = Git::Commitish(repo, commitish); isBranch = git_reference_is_branch(ref.get()); } update(); } void GitFS::Repo::update() { if (!commit || (isBranch && ref && resolvedAt < std::time(nullptr) - 30)) { commit = Git::CommitLookup(repo, *git_reference_target(Git::Resolve(ref).get())); resolvedAt = std::time(nullptr); } tree = Git::TreeLookup(repo, *git_commit_tree_id(commit.get())); } void GitFS::Repo::disconnect(const ::Ice::Current & current) { current.adapter->remove(current.id); } NetFS::DirectoryPrxPtr GitFS::Repo::opendir(ReqEnv, ::std::string path, const ::Ice::Current & ice) { if (path.empty()) { throw NetFS::SystemError(EINVAL); } return Ice::uncheckedCast( ice.adapter->addWithUUID(std::make_shared(this, std::move(path)))); } NetFS::VFS GitFS::Repo::statfs(ReqEnv, ::std::string path, const ::Ice::Current &) { if (path.empty()) { throw NetFS::SystemError(EINVAL); } return {}; } int GitFS::Repo::access(ReqEnv, ::std::string path, int mode, const ::Ice::Current &) { if (mode & W_OK) { return EACCES; } if (path.empty()) { return EINVAL; } if (path == "/") { return 0; } try { update(); auto e = Git::TreeEntryByPath(tree, path); const auto emode = git_tree_entry_filemode(e.get()); if (S_ISDIR(emode)) { return 0; } if (S_ISLNK(emode)) { return 0; } if (mode & R_OK && !(S_IRUSR & emode)) { return EACCES; } if (mode & X_OK && !(S_IXUSR & emode)) { return EACCES; } return 0; } catch (const NetFS::SystemError & e) { return e.syserrno; } } NetFS::Attr GitFS::Repo::getattr(ReqEnv, ::std::string path, const ::Ice::Current &) { if (path.empty()) { throw NetFS::SystemError(EINVAL); } NetFS::Attr a {}; if (path == "/") { a.mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; } else { update(); auto entry = Git::TreeEntryByPath(tree, path); a << *entry; if (S_ISREG(git_tree_entry_filemode(entry.get()))) { auto blob = Git::BlobLookup(repo, *git_tree_entry_id(entry.get())); a << *blob; } } a << *commit; a.gid = gid; a.uid = uid; return a; } ::std::string GitFS::Repo::readlink(ReqEnv, ::std::string path, const ::Ice::Current &) { if (path.empty() || path == "/") { throw NetFS::SystemError(EINVAL); } update(); auto e = Git::TreeEntryByPath(tree, path); if (!S_ISLNK(git_tree_entry_filemode(e.get()))) { throw NetFS::SystemError(EINVAL); } auto blob = Git::BlobLookup(repo, *git_tree_entry_id(e.get())); auto n = static_cast(git_blob_rawcontent(blob.get())); return {n, n + git_blob_rawsize(blob.get())}; } NetFS::FilePrxPtr GitFS::Repo::open(ReqEnv, ::std::string path, int, const ::Ice::Current & ice) { if (path.empty()) { throw NetFS::SystemError(EINVAL); } if (path == "/") { throw NetFS::SystemError(EISDIR); } update(); return Ice::uncheckedCast(ice.adapter->addWithUUID(std::make_shared(this, std::move(path)))); } NetFS::FilePrxPtr GitFS::Repo::create(ReqEnv, ::std::string, int, int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::truncate(ReqEnv, ::std::string, long long int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::unlink(ReqEnv, ::std::string, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::mkdir(ReqEnv, ::std::string, int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::rmdir(ReqEnv, ::std::string, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::mknod(ReqEnv, ::std::string, int, int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::symlink(ReqEnv, ::std::string, ::std::string, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::link(ReqEnv, ::std::string, ::std::string, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::rename(ReqEnv, ::std::string, ::std::string, const Ice::optional, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::chmod(ReqEnv, ::std::string, int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::chown(ReqEnv, ::std::string, int, int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); } void GitFS::Repo::utimens( ReqEnv, ::std::string, long long int, long long int, long long int, long long int, const ::Ice::Current &) { throw NetFS::SystemError(EROFS); }