copy command
This commit is contained in:
parent
19fba4c605
commit
446aa5adbc
7 changed files with 121 additions and 9 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue