link initial unstable

This commit is contained in:
IlyaShurupov 2024-03-28 15:52:07 +03:00
parent 3138b0aad3
commit 21e8730f41
5 changed files with 105 additions and 8 deletions

View file

@ -63,12 +63,14 @@ public:
class Link : public Node {
public:
Link();
Link(Node* target, bool isHard);
Link(const Link& node);
[[nodiscard]] Link* clone() const override;
[[nodiscard]] Node* getLink() const;
[[nodiscard]] bool isHard() const;
void setHard(bool);
private:
Node* mLink = nullptr;
@ -103,7 +105,7 @@ public:
}
void getNodePath(Node* node, std::vector<const Key*>& path) const;
ui64 size() const;
[[nodiscard]] ui64 size() const;
private:
void updateTreeLinkCount(Node* node);

View file

@ -29,10 +29,11 @@ public:
bool removeFileOrLink(const Path& path);
bool copyNode(const Path& source, const Path& to);
bool moveNode(const Path& source, const Path& to);
bool makeLink(const Path& source, const Path& to, bool isDynamic);
void log() const;
const std::string& getLastError();
static const std::string& getLastError();
private:
bool isPathContainsCurrent(Node* node);

View file

@ -4,6 +4,7 @@
#include <sstream>
std::string gError;
bool gDebug = true;
Node::~Node() = default;
@ -27,14 +28,25 @@ File *File::clone() const {
return new File(*this);
}
Link::Link() {
Link::Link(Node* target, bool isHard) {
mType = LINK;
mIsHard = isHard;
mLink = target;
}
Node *Link::getLink() const {
return mLink;
}
bool Link::isHard() const {
return mIsHard;
}
void Link::setHard(bool val) {
mIsHard = val;
// TODO : do we need to update cache here?
}
Link::Link(const Link &node) : Node(node) {
mLink = node.mLink;
mIsHard = node.mIsHard;
@ -133,6 +145,7 @@ Node* Directory::findNode(const std::vector<Key>& path, ui32 currentDepth) {
return ((Directory*)node)->findNode(path, ++currentDepth);
case Node::LINK:
if (currentDepth == path.size() - 1) return node;
node = ((Link*)node)->getLink();
break;
@ -186,15 +199,34 @@ void Directory::dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector<b
if (lastNode == node) indents[currentDepth - 1] = false;
indent(ss, currentDepth, indents);
ss << node->key.val << "\n";
switch (node->data->mType) {
case Node::DIRECTORY:
ss << node->key.val;
if (gDebug) ss << " [" << node->key.incomingLinksHard << ":" << node->key.incomingLinksDynamic << "]";
ss << "\n";
((Directory*) node->data)->dumpUtil(ss, currentDepth, indents);
return;
case Node::LINK: {
auto linkNode = ((Link*)node->data);
ss << node->key.val << (linkNode->isHard() ? " hlink[/" : " dlink[/");
std::vector<const Key*> path;
getNodePath(linkNode->getLink(), path);
std::reverse(path.begin(), path.end());
for (auto key : path) ss << *key << "/";
ss << "]\n";
return;
}
case Node::FILE:
ss << node->key.val;
if (gDebug) ss << " [file]";
ss << "\n";
return;
default:
// do nothing for now
ss << " ERROR \n";
return;
}
});
@ -212,8 +244,12 @@ ui64 Directory::size() const {
Directory::Directory(const Directory &node) : Node(node) {
node.traverseInorder([&](const DirectoryTree::Node* node){
mMembers.insert(node->key, node->data->clone());
auto newNode = node->data->clone();
mMembers.insert(node->key, newNode);
newNode->mParent = this;
});
updateTreeLinkCount(this);
}
Directory *Directory::clone() const {

View file

@ -176,6 +176,48 @@ bool FileSystem::moveNode(const Path &source, const Path &target) {
return true;
}
bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
// TODO : remove code duplication
Directory* workingDirectorySource = source.isAbsolute() ? root : currentDirectory;
Directory* workingDirectoryTarget = target.isAbsolute() ? root : currentDirectory;
auto sourceNode = workingDirectorySource->findNode(source.getChain());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
if (sourceNode->mType == Node::LINK) {
gError = "Link on link is not allowed";
return false;
}
auto targetNode = workingDirectoryTarget->findNode(target.getChain());
if (!targetNode || targetNode->mType != Node::DIRECTORY) {
gError = "Invalid target directory";
return false;
}
const Key& key = sourceNode->mTreeNode->key.val;
auto targetDirectory = (Directory*)targetNode;
if (targetDirectory->findNode(key)) {
gError = "Node with such name already exists in the target directory";
return false;
}
auto newLink = new Link(sourceNode, !isDynamic);
assert(targetDirectory->attachNode(key, newLink));
return true;
}
bool FileSystem::removeFileOrLink(const Path &path) {
if (path.getDepth() < 1 || path.isInvalid()) {
gError = "Invalid path";

View file

@ -73,6 +73,22 @@ Interpreter::Interpreter() {
return filesystem.moveNode(args[1], args[2]);
}
};
mCommands["mhl"] = {
"make hard link",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.makeLink(args[1], args[2], false);
}
};
mCommands["mdl"] = {
"make dynamic link",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.makeLink(args[1], args[2], true);
}
};
}
void Interpreter::reportError(const std::string& description) {
@ -116,7 +132,7 @@ void Interpreter::interpret(const std::string& command) {
bool success = iter->second.callback(mFileSystem, words);
if (!success) {
reportError(mFileSystem.getLastError());
reportError(FileSystem::getLastError());
return;
}