diff options
| author | Stefan Boberg <[email protected]> | 2023-05-16 21:27:00 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2023-05-16 21:27:00 +0200 |
| commit | 6611243ddccdfc583f4fb779e52ba669c2ca2bbf (patch) | |
| tree | 2d602a2c4c33bea5a2d9615e317ad18e15886b8b /src | |
| parent | demote state_marker deletion detection to warning (diff) | |
| download | zen-6611243ddccdfc583f4fb779e52ba669c2ca2bbf.tar.xz zen-6611243ddccdfc583f4fb779e52ba669c2ca2bbf.zip | |
implemented subtree copying
Diffstat (limited to 'src')
| -rw-r--r-- | src/zen/cmds/copy.cpp | 107 |
1 files changed, 103 insertions, 4 deletions
diff --git a/src/zen/cmds/copy.cpp b/src/zen/cmds/copy.cpp index 6f6c078d4..6fff973ba 100644 --- a/src/zen/cmds/copy.cpp +++ b/src/zen/cmds/copy.cpp @@ -3,6 +3,7 @@ #include "copy.h" #include <zencore/filesystem.h> +#include <zencore/fmtutils.h> #include <zencore/logging.h> #include <zencore/string.h> #include <zencore/timer.h> @@ -15,8 +16,7 @@ CopyCommand::CopyCommand() m_Options.add_options()("no-clone", "Do not perform block clone", cxxopts::value(m_NoClone)->default_value("false")); m_Options.add_option("", "s", "source", "Copy source", cxxopts::value(m_CopySource), "<file/directory>"); m_Options.add_option("", "t", "target", "Copy target", cxxopts::value(m_CopyTarget), "<file/directory>"); - m_Options.add_option("", "", "positional", "Positional arguments", cxxopts::value(m_Positional), ""); - m_Options.parse_positional({"source", "target", "positional"}); + m_Options.parse_positional({"source", "target"}); } CopyCommand::~CopyCommand() = default; @@ -75,6 +75,89 @@ CopyCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { std::filesystem::create_directories(ToPath); } + + // Multi file copy + + ZEN_CONSOLE("copying {} -> {}", FromPath, ToPath); + + zen::Stopwatch Timer; + + struct CopyVisitor : public FileSystemTraversal::TreeVisitor + { + CopyVisitor(std::filesystem::path InBasePath, zen::CopyFileOptions InCopyOptions) + : BasePath(InBasePath) + , CopyOptions(InCopyOptions) + { + } + + virtual void VisitFile(const std::filesystem::path& Parent, const path_view& File, uint64_t FileSize) override + { + ZEN_UNUSED(FileSize); + std::error_code Ec; + const std::filesystem::path Relative = std::filesystem::relative(Parent, BasePath, Ec); + + if (Ec) + { + FailedFileCount++; + } + else + { + const std::filesystem::path FromPath = Parent / File; + const std::filesystem::path ToPath = TargetPath / Relative / File; + + try + { + zen::CreateDirectories(TargetPath / Relative); + if (zen::CopyFile(FromPath, ToPath, CopyOptions)) + { + ++FileCount; + ByteCount += FileSize; + } + else + { + throw std::logic_error("CopyFile failed in an unexpected way"); + } + } + catch (std::exception& Ex) + { + ++FailedFileCount; + + ZEN_CONSOLE("Error: failed to copy '{}' to '{}': '{}'", FromPath, ToPath, Ex.what()); + } + } + } + + virtual bool VisitDirectory(const std::filesystem::path&, const path_view&) override { return true; } + + std::filesystem::path BasePath; + std::filesystem::path TargetPath; + zen::CopyFileOptions CopyOptions; + int FileCount = 0; + uint64_t ByteCount = 0; + int FailedFileCount = 0; + }; + + zen::CopyFileOptions CopyOptions; + CopyOptions.EnableClone = !m_NoClone; + + CopyVisitor Visitor{FromPath, CopyOptions}; + Visitor.TargetPath = ToPath; + + FileSystemTraversal Traversal; + Traversal.TraverseFileSystem(FromPath, Visitor); + + ZEN_CONSOLE("Copy of {} files ({}) completed in {} ({})", + Visitor.FileCount, + NiceBytes(Visitor.ByteCount), + zen::NiceTimeSpanMs(Timer.GetElapsedTimeMs()), + zen::NiceRate(Visitor.ByteCount, (uint32_t)Timer.GetElapsedTimeMs())); + + if (Visitor.FailedFileCount) + { + ZEN_CONSOLE("{} file copy operations FAILED"); + + return 1; + } } else { @@ -84,9 +167,25 @@ CopyCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) zen::CopyFileOptions CopyOptions; CopyOptions.EnableClone = !m_NoClone; - zen::CopyFile(FromPath, ToPath, CopyOptions); - ZEN_CONSOLE("Copy completed in {}", zen::NiceTimeSpanMs(Timer.GetElapsedTimeMs())); + try + { + zen::CreateDirectories(ToPath.parent_path()); + if (zen::CopyFile(FromPath, ToPath, CopyOptions)) + { + ZEN_CONSOLE("Copy completed in {}", zen::NiceTimeSpanMs(Timer.GetElapsedTimeMs())); + } + else + { + throw std::logic_error("CopyFile failed in an unexpected way"); + } + } + catch (std::exception& Ex) + { + ZEN_CONSOLE("Error: failed to copy '{}' to '{}': '{}'", FromPath, ToPath, Ex.what()); + + return 1; + } } return 0; |