tmp unstable
This commit is contained in:
parent
abca7aeb76
commit
b5ddd765eb
8 changed files with 101 additions and 47 deletions
|
|
@ -17,7 +17,20 @@ public:
|
|||
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0) override;
|
||||
std::shared_ptr<Node> findNode(const Key& path) override;
|
||||
[[nodiscard]] ui64 size() const override;
|
||||
bool isDirectory() const override { return true; }
|
||||
|
||||
void clearFlags(std::shared_ptr<Node>& directory) override;
|
||||
bool isHard() const override;
|
||||
void removeIncomingDynamicLinks() override;
|
||||
|
||||
template <typename tFunctor>
|
||||
static void traverse(std::shared_ptr<Node>& node, tFunctor functor) {
|
||||
functor(node);
|
||||
if (std::shared_ptr<Directory> directory = std::dynamic_pointer_cast<Directory>(node)) {
|
||||
for (auto& member : directory->mMembers) {
|
||||
traverse(member.second, functor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const;
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ public:
|
|||
// link on link is not allowed, so no inf looping here
|
||||
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth) override;
|
||||
void dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) override;
|
||||
bool isLink() const override { return true; }
|
||||
|
||||
static bool linkNodes(const std::shared_ptr<Link>& link, const std::shared_ptr<Node>& target, bool hard);
|
||||
static bool unlinkWithIncomingLinks(std::shared_ptr<Node>& target);
|
||||
static bool removeOutgoingLinks(const std::shared_ptr<Link>& link);
|
||||
|
||||
private:
|
||||
std::weak_ptr<Node> mLink;
|
||||
|
|
|
|||
11
inc/Node.hpp
11
inc/Node.hpp
|
|
@ -13,6 +13,7 @@ typedef long i32;
|
|||
#include <memory>
|
||||
|
||||
class Link;
|
||||
class Directory;
|
||||
|
||||
typedef std::string Key;
|
||||
|
||||
|
|
@ -35,9 +36,10 @@ public:
|
|||
virtual std::shared_ptr<Node> getTarget();
|
||||
virtual std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
|
||||
virtual std::shared_ptr<Node> findNode(const Key& path) { return nullptr; }
|
||||
virtual bool isDirectory() const { return false; }
|
||||
virtual bool isLink() const { return false; }
|
||||
virtual bool isHard() const { return false; }
|
||||
|
||||
virtual void clearFlags(std::shared_ptr<Node>& directory) {}
|
||||
virtual bool isHard() const;
|
||||
virtual void removeIncomingDynamicLinks();
|
||||
|
||||
ui32 getMaxDepth() const;
|
||||
void dump(std::stringstream& ss);
|
||||
|
|
@ -46,8 +48,9 @@ public:
|
|||
static void indent(std::stringstream & ss, ui32 depth, std::vector<bool>& indents);
|
||||
|
||||
public:
|
||||
Key mKey;
|
||||
std::weak_ptr<Node> mWorkingNodeFlag;
|
||||
std::weak_ptr<Node> mParent;
|
||||
|
||||
std::vector<std::weak_ptr<Link>> mIncomingHardLinks;
|
||||
std::vector<std::weak_ptr<Link>> mIncomingDynamicLinks;
|
||||
};
|
||||
|
|
@ -11,17 +11,12 @@ Directory::~Directory() = default;
|
|||
bool Directory::attachNode(const Key &newKey, std::shared_ptr<Node> newNode) {
|
||||
assert(mMembers.find(newKey) == mMembers.end());
|
||||
mMembers.insert({ newKey, newNode });
|
||||
newNode->mKey = newKey;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Directory::detachNode(const Key& key) {
|
||||
assert(mMembers.find(key) != mMembers.end());
|
||||
|
||||
//if (removeNode->key.incomingLinksHard || removeNode->key.incomingLinksDynamic) {
|
||||
// gError = "Cannot modify node with incoming hard links";
|
||||
// return false;
|
||||
//}
|
||||
|
||||
mMembers.erase(key);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -92,3 +87,20 @@ std::shared_ptr<Node> Directory::clone() const {
|
|||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void Directory::clearFlags(std::shared_ptr<Node> &directory) {
|
||||
traverse(directory, [&](std::shared_ptr<Node>& node) {
|
||||
node->mWorkingNodeFlag = directory;
|
||||
});
|
||||
}
|
||||
|
||||
bool Directory::isHard() const {
|
||||
return std::any_of(mMembers.begin(), mMembers.end(), [](const auto& member) { return member.second->isHard(); });
|
||||
}
|
||||
|
||||
void Directory::removeIncomingDynamicLinks() {
|
||||
Node::removeIncomingDynamicLinks();
|
||||
for (auto& member : mMembers) {
|
||||
member.second->removeIncomingDynamicLinks();
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ bool FileSystem::changeCurrent(const Path& path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!parentNode->isDirectory()) {
|
||||
if (parentNode->getType() != Node::DIRECTORY) {
|
||||
gError = "Path is not a directory";
|
||||
return false;
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sourceNode->isLink()) {
|
||||
if (sourceNode->getType() == Node::LINK) {
|
||||
gError = "Link on link is not allowed";
|
||||
return false;
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ bool FileSystem::removeDirectory(const Path& path, bool recursively) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!existingNode->isDirectory()) {
|
||||
if (existingNode->getType() != Node::DIRECTORY) {
|
||||
gError = "Path is not a directory";
|
||||
return false;
|
||||
}
|
||||
|
|
@ -194,6 +194,15 @@ bool FileSystem::removeDirectory(const Path& path, bool recursively) {
|
|||
return false;
|
||||
}
|
||||
|
||||
existingNode->clearFlags(parentNode);
|
||||
if (existingNode->isHard()) {
|
||||
gError = "Directory is referenced by a hard links";
|
||||
return false;
|
||||
}
|
||||
|
||||
// deletes dynamic incoming links to this file system sub-ree
|
||||
existingNode->removeIncomingDynamicLinks();
|
||||
|
||||
if (!parentNode->detachNode(path.getFilename())) {
|
||||
gError = "Can not remove directory because it has hard references";
|
||||
return false;
|
||||
|
|
@ -221,11 +230,17 @@ bool FileSystem::removeFileOrLink(const Path &path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (existingNode->isDirectory()) {
|
||||
if (existingNode->getType() == Node::DIRECTORY) {
|
||||
gError = "Path is not a file or a link";
|
||||
return false;
|
||||
}
|
||||
|
||||
existingNode->clearFlags(parentNode);
|
||||
if (existingNode->isHard()) {
|
||||
gError = "File or link is referenced by a hard links";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parentNode->detachNode(path.getFilename())) {
|
||||
gError = "Can not remove file or link because it has hard references";
|
||||
return false;
|
||||
|
|
@ -256,9 +271,9 @@ bool FileSystem::copyNode(const Path& source, const Path& target) {
|
|||
if (!sourceNode) {
|
||||
gError = "Invalid source path";
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (!parentNodeTarget->isDirectory()) {
|
||||
if (parentNodeTarget->getType() != Node::DIRECTORY) {
|
||||
gError = "Target path is not a directory";
|
||||
return false;
|
||||
}
|
||||
|
|
@ -308,8 +323,9 @@ bool FileSystem::moveNode(const Path &source, const Path &target) {
|
|||
return false;
|
||||
}
|
||||
|
||||
sourceNode->clearFlags(parentNodeSource);
|
||||
if (sourceNode->isHard()) {
|
||||
gError = "Node contains incoming hard links";
|
||||
gError = "Node is referenced by a hard links";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -327,9 +343,9 @@ void FileSystem::log() const {
|
|||
root->getNodeStraightPath(currentDirectory, currentPath);
|
||||
std::reverse(currentPath.begin(), currentPath.end());
|
||||
|
||||
ss << "cd - /";
|
||||
for (auto key : currentPath) {
|
||||
ss << "X" << "/";
|
||||
ss << "cd - ";
|
||||
for (const auto& node : currentPath) {
|
||||
ss << node->mKey << "/";
|
||||
}
|
||||
|
||||
ss << "\n";
|
||||
|
|
|
|||
26
src/Link.cpp
26
src/Link.cpp
|
|
@ -32,26 +32,6 @@ bool Link::linkNodes(const std::shared_ptr<Link>& link, const std::shared_ptr<No
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Link::unlinkWithIncomingLinks(std::shared_ptr<Node>& target) {
|
||||
assert(target->mIncomingHardLinks.empty());
|
||||
auto& links = target->mIncomingDynamicLinks;
|
||||
|
||||
auto shouldRemove = [](const std::weak_ptr<Link>& link) {
|
||||
// Modify the condition as needed
|
||||
return link.expired(); // Remove expired weak pointers
|
||||
};
|
||||
|
||||
links.erase(std::remove_if(links.begin(), links.end(), shouldRemove), links.end());
|
||||
}
|
||||
|
||||
bool Link::removeOutgoingLinks(const std::shared_ptr<Link>& link) {
|
||||
// assert(mLink);
|
||||
// auto& links = mIsHard ? mLink->mIncomingHardLinks : mLink->mIncomingDynamicLinks;
|
||||
// links.erase(std::remove(links.begin(), links.end(), this), links.end());
|
||||
// Directory::updateTreeLinkCount(mLink);
|
||||
// mLink = nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Link::getLink() const {
|
||||
auto target = mLink.lock();
|
||||
assert(target);
|
||||
|
|
@ -73,12 +53,12 @@ std::shared_ptr<Node> Link::findNode(const std::vector<Key>& path, ui32 currentD
|
|||
|
||||
void Link::dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) {
|
||||
indent(ss, currentDepth, indents);
|
||||
ss << key << (isHard() ? " hlink[/" : " dlink[/");
|
||||
ss << key << (isHard() ? " hlink[" : " dlink[");
|
||||
std::vector<std::shared_ptr<Node>> path;
|
||||
getNodeStraightPath(getLink(), path);
|
||||
std::reverse(path.begin(), path.end());
|
||||
for (auto tmp : path)
|
||||
ss << "X" << "/";
|
||||
for (auto& node : path)
|
||||
ss << node->mKey << "/";
|
||||
ss << "]\n";
|
||||
}
|
||||
|
||||
|
|
|
|||
32
src/Node.cpp
32
src/Node.cpp
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "Node.hpp"
|
||||
#include "Link.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
|
@ -31,6 +32,37 @@ std::shared_ptr<Node> Node::findNode(const std::vector<Key>& path, ui32 currentD
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool Node::isHard() const {
|
||||
return std::any_of(mIncomingHardLinks.begin(), mIncomingHardLinks.end(), [this](const std::weak_ptr<Link>& hardLink) {
|
||||
auto linkNode = hardLink.lock();
|
||||
assert(linkNode);
|
||||
auto linkTarget = linkNode->getLink()->mWorkingNodeFlag.lock();
|
||||
assert(linkTarget);
|
||||
auto ownLink = mWorkingNodeFlag.lock();
|
||||
|
||||
// if hard link in the same working tree it does not count
|
||||
return ownLink != linkTarget;
|
||||
});
|
||||
}
|
||||
|
||||
void Node::removeIncomingDynamicLinks() {
|
||||
for (auto& dynamicLink : mIncomingDynamicLinks) {
|
||||
auto linkNode = dynamicLink.lock();
|
||||
assert(linkNode);
|
||||
auto linkTarget = linkNode->getLink()->mWorkingNodeFlag.lock();
|
||||
assert(linkTarget);
|
||||
auto ownLink = mWorkingNodeFlag.lock();
|
||||
|
||||
if (ownLink == linkTarget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto parentNode = linkNode->mParent.lock();
|
||||
assert(parentNode);
|
||||
parentNode->detachNode(linkNode->mKey);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Node::getTarget() {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ int main() {
|
|||
interpreter.interpret("md a/b/c");
|
||||
interpreter.interpret("mhl a /a/b/c/");
|
||||
interpreter.interpret("md a/b/c/a/k");
|
||||
|
||||
interpreter.interpret("copy a /");
|
||||
|
||||
interpreter.interpret("mdl a/b/c /a_copy/k");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue