From 446aa5adbcf9d5e7c1eee0d609ed6ac6c3f8edc8 Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Thu, 28 Mar 2024 14:32:35 +0300 Subject: [PATCH] copy command --- inc/DirectoryTree.hpp | 18 +++++++++++++ inc/FileSystem.hpp | 1 + src/DirectoryTree.cpp | 60 ++++++++++++++++++++++++++++++++++++------- src/FileSystem.cpp | 37 ++++++++++++++++++++++++++ src/Interpreter.cpp | 8 ++++++ src/Path.cpp | 1 + test/Tests.cpp | 5 ++++ 7 files changed, 121 insertions(+), 9 deletions(-) diff --git a/inc/DirectoryTree.hpp b/inc/DirectoryTree.hpp index d5ab24a..6b8ce78 100644 --- a/inc/DirectoryTree.hpp +++ b/inc/DirectoryTree.hpp @@ -41,8 +41,12 @@ public: enum Type : ui32 { NONE, DIRECTORY, FILE, LINK } ; public: + Node() = default; + Node(const Node& node); virtual ~Node(); + [[nodiscard]] virtual Node* clone() const; + public: Type mType = NONE; Node* mParent = nullptr; @@ -52,11 +56,18 @@ public: class File : public Node { public: File(); + File(const File& node); + + [[nodiscard]] File* clone() const override; }; class Link : public Node { public: Link(); + Link(const Link& node); + + [[nodiscard]] Link* clone() const override; + [[nodiscard]] Node* getLink() const; private: @@ -67,13 +78,20 @@ private: class Directory : public Node { public: Directory(); + Directory(const Directory& node); + ~Directory() override; + [[nodiscard]] Directory* clone() const override; + void dump(std::stringstream& ss); bool attachNode(const std::vector& directoryPath, const Key& newKey, Node* newNode); bool detachNode(const std::vector& directoryPath, const Key& key); + + bool attachNode(const Key &newKey, Node *newNode); Node* findNode(const std::vector& path, ui32 currentDepth = 0); + Node* findNode(const Key& path); [[nodiscard]] ui32 getMaxDepth() const; diff --git a/inc/FileSystem.hpp b/inc/FileSystem.hpp index 05b7636..302612a 100644 --- a/inc/FileSystem.hpp +++ b/inc/FileSystem.hpp @@ -29,6 +29,7 @@ public: bool changeCurrent(const Path& path); bool removeDirectory(const Path& path, bool recursively); bool removeFileOrLink(const Path& path); + bool copyNode(const Path& source, const Path& to); void log() const; diff --git a/src/DirectoryTree.cpp b/src/DirectoryTree.cpp index 5231bae..19c0f37 100644 --- a/src/DirectoryTree.cpp +++ b/src/DirectoryTree.cpp @@ -7,10 +7,26 @@ std::string gError; Node::~Node() = default; +Node::Node(const Node &node) { + mType = node.mType; +} + +Node *Node::clone() const { + return new Node(*this); +} + File::File() { mType = Type::FILE; } +File::File(const File& node) : Node(node) { + // nothing to do +} + +File *File::clone() const { + return new File(*this); +} + Link::Link() { mType = LINK; } @@ -19,6 +35,15 @@ Node *Link::getLink() const { return mLink; } +Link::Link(const Link &node) : Node(node) { + mLink = node.mLink; + mIsHard = node.mIsHard; +} + +Link *Link::clone() const { + return new Link(*this); +} + Directory::Directory() { mType = DIRECTORY; } @@ -36,19 +61,21 @@ bool Directory::attachNode(const std::vector& directoryPath, const Key& new return false; } - auto directory = ((Directory*) node); + return ((Directory*) node)->attachNode(newKey, newNode); +} - DirectoryTree::Node* iterNode = directory->mMembers.find(DirectoryKey(newKey)); +bool Directory::attachNode(const Key &newKey, Node *newNode) { + DirectoryTree::Node* iterNode = mMembers.find(DirectoryKey(newKey)); if (iterNode) { if (iterNode->data->mType == newNode->mType) return false; // exit silently - gError = "Cant add node"; + gError = "Can not add node"; return false; } - directory->mMembers.insert(DirectoryKey(newKey), newNode); + mMembers.insert(DirectoryKey(newKey), newNode); - newNode->mParent = directory; - updateTreeLinkCount(directory); + newNode->mParent = this; + updateTreeLinkCount(this); return true; } @@ -67,13 +94,18 @@ bool Directory::detachNode(const std::vector& directoryPath, const Key& key return false; } - directory->mMembers.remove(DirectoryKey(key)); removeNode->mParent = nullptr; + directory->mMembers.remove(DirectoryKey(key)); updateTreeLinkCount(directory); return true; } +Node* Directory::findNode(const Key& key) { + DirectoryTree::Node* iterNode = mMembers.find(DirectoryKey(key)); + return iterNode ? iterNode->data : nullptr; +} + Node* Directory::findNode(const std::vector& path, ui32 currentDepth) { if (path.size() == currentDepth) { return this; @@ -140,7 +172,7 @@ static void indent(std::stringstream & ss, ui32 depth, std::vector& indent for (auto i = 0; i < depth - 1; i++) { ss << (indents[i] ? " |" : " "); } - ss << " |_"; + ss << " |_ "; } void Directory::dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector& indents) { @@ -174,4 +206,14 @@ void Directory::getNodePath(Node* node, std::vector& path) const { ui64 Directory::size() const { return mMembers.size(); -} \ No newline at end of file +} + +Directory::Directory(const Directory &node) : Node(node) { + node.traverseInorder([&](const DirectoryTree::Node* node){ + mMembers.insert(node->key, node->data->clone()); + }); +} + +Directory *Directory::clone() const { + return new Directory(*this); +} diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp index 6344ca3..4a0c0e8 100644 --- a/src/FileSystem.cpp +++ b/src/FileSystem.cpp @@ -98,6 +98,43 @@ bool FileSystem::removeDirectory(const Path& path, bool recursively) { return true; } +bool FileSystem::copyNode(const Path& source, const Path& target) { + if (source.getDepth() < 1 || source.isInvalid()) { + gError = "Invalid source path"; + return false; + } + + 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; + } + + auto targetNode = workingDirectoryTarget->findNode(target.getChain()); + if (!targetNode || targetNode->mType != Node::DIRECTORY) { + gError = "Invalid target directory"; + return false; + } + + auto targetDirectory = (Directory*)targetNode; + + Key key = sourceNode->mTreeNode->key.val; + + if (targetDirectory->findNode(key)) { + // gError = "Node with such name already exists in the target directory"; + // return false; + key += "-copy"; + } + + Node* clonedNode = sourceNode->clone(); + assert(targetDirectory->attachNode(key, clonedNode)); + + return true; +} + bool FileSystem::removeFileOrLink(const Path &path) { if (path.getDepth() < 1 || path.isInvalid()) { gError = "Invalid path"; diff --git a/src/Interpreter.cpp b/src/Interpreter.cpp index 2f4599c..6ed31af 100644 --- a/src/Interpreter.cpp +++ b/src/Interpreter.cpp @@ -57,6 +57,14 @@ Interpreter::Interpreter() { return filesystem.removeFileOrLink(args[1]); } }; + + mCommands["copy"] = { + "recursive copy of a node", + 2, + [](FileSystem& filesystem, const std::vector& args){ + return filesystem.copyNode(args[1], args[2]); + } + }; } void Interpreter::reportError(const std::string& description) { diff --git a/src/Path.cpp b/src/Path.cpp index ae402fd..7cfa212 100644 --- a/src/Path.cpp +++ b/src/Path.cpp @@ -11,6 +11,7 @@ void initializeTransitions() { for (char i = 'A'; i <= 'Z'; i++) transitions[i] = i /* + ('a' - 'A')*/; transitions['/'] = '/'; transitions['.'] = '.'; + transitions['-'] = '-'; } Path::Path(const std::string& path) { diff --git a/test/Tests.cpp b/test/Tests.cpp index 3eff872..86ee604 100644 --- a/test/Tests.cpp +++ b/test/Tests.cpp @@ -18,7 +18,12 @@ int main() { interpreter.interpret("cd asd/b/c/d"); + interpreter.interpret("cd /"); + + interpreter.interpret("copy A123 / "); + interpreter.interpret("rd d"); + interpreter.interpret("deltree A123"); return UnitTest::RunAllTests(); } \ No newline at end of file