copy command

This commit is contained in:
IlyaShurupov 2024-03-28 14:32:35 +03:00
parent 19fba4c605
commit 446aa5adbc
7 changed files with 121 additions and 9 deletions

View file

@ -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<Key>& directoryPath, const Key& newKey, Node* newNode);
bool detachNode(const std::vector<Key>& directoryPath, const Key& key);
bool attachNode(const Key &newKey, Node *newNode);
Node* findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
Node* findNode(const Key& path);
[[nodiscard]] ui32 getMaxDepth() const;

View file

@ -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;

View file

@ -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<Key>& 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<Key>& 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<Key>& path, ui32 currentDepth) {
if (path.size() == currentDepth) {
return this;
@ -140,7 +172,7 @@ static void indent(std::stringstream & ss, ui32 depth, std::vector<bool>& indent
for (auto i = 0; i < depth - 1; i++) {
ss << (indents[i] ? " |" : " ");
}
ss << " |_";
ss << " |_ ";
}
void Directory::dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector<bool>& indents) {
@ -174,4 +206,14 @@ void Directory::getNodePath(Node* node, std::vector<const Key*>& path) const {
ui64 Directory::size() const {
return mMembers.size();
}
}
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);
}

View file

@ -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";

View file

@ -57,6 +57,14 @@ Interpreter::Interpreter() {
return filesystem.removeFileOrLink(args[1]);
}
};
mCommands["copy"] = {
"recursive copy of a node",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.copyNode(args[1], args[2]);
}
};
}
void Interpreter::reportError(const std::string& description) {

View file

@ -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) {

View file

@ -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();
}