diff options
Diffstat (limited to 'src/zen/cmds/copy_cmd.cpp')
| -rw-r--r-- | src/zen/cmds/copy_cmd.cpp | 207 |
1 files changed, 0 insertions, 207 deletions
diff --git a/src/zen/cmds/copy_cmd.cpp b/src/zen/cmds/copy_cmd.cpp deleted file mode 100644 index 530661607..000000000 --- a/src/zen/cmds/copy_cmd.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "copy_cmd.h" - -#include <zencore/filesystem.h> -#include <zencore/fmtutils.h> -#include <zencore/logging.h> -#include <zencore/string.h> -#include <zencore/timer.h> - -namespace zen { - -CopyCommand::CopyCommand() -{ - m_Options.add_options()("h,help", "Print help"); - m_Options.add_options()("no-clone", "Do not perform block clone", cxxopts::value(m_NoClone)->default_value("false")); - m_Options.add_options()("must-clone", - "Always perform block clone (fails if clone is not possible)", - cxxopts::value(m_MustClone)->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.parse_positional({"source", "target"}); -} - -CopyCommand::~CopyCommand() = default; - -void -CopyCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) -{ - ZEN_UNUSED(GlobalOptions); - - if (!ParseOptions(argc, argv)) - { - return; - } - - // Validate arguments - - if (m_CopySource.empty()) - throw OptionParseException("'--source' is required", m_Options.help()); - - if (m_CopyTarget.empty()) - throw OptionParseException("'--target' is required", m_Options.help()); - - std::filesystem::path FromPath = m_CopySource; - std::filesystem::path ToPath = m_CopyTarget; - - std::error_code Ec; - std::filesystem::path FromCanonical = std::filesystem::canonical(FromPath, Ec); - - if (!Ec) - { - std::filesystem::path ToCanonical = std::filesystem::canonical(ToPath, Ec); - - if (!Ec) - { - if (FromCanonical == ToCanonical) - { - throw std::runtime_error("Target and source must be distinct files or directories"); - } - } - } - - const bool IsFileCopy = IsFile(m_CopySource); - const bool IsDirCopy = IsDir(m_CopySource); - - if (!IsFileCopy && !IsDirCopy) - { - throw std::runtime_error("Invalid source specification (neither directory nor file)"); - } - - if (IsFileCopy && IsDirCopy) - { - throw std::runtime_error("Invalid source specification (both directory AND file!?)"); - } - - if (IsDirCopy) - { - if (IsFile(ToPath)) - { - throw std::runtime_error("Attempted copy of directory into file"); - } - - if (!IsDir(ToPath)) - { - CreateDirectories(ToPath); - } - - std::filesystem::path ToCanonical = std::filesystem::canonical(ToPath, Ec); - - if (!Ec) - { - if (ToCanonical.generic_string().starts_with(FromCanonical.generic_string()) || - FromCanonical.generic_string().starts_with(ToCanonical.generic_string())) - { - throw std::runtime_error("Invalid parent/child relationship for source/target directories"); - } - } - - // 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, - uint32_t, - uint64_t) 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 (const 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&, uint32_t) 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; - CopyOptions.MustClone = m_MustClone; - - 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) - { - throw std::runtime_error(fmt::format("{} file copy operations FAILED", Visitor.FailedFileCount)); - } - } - else - { - // Single file copy - - zen::Stopwatch Timer; - - zen::CopyFileOptions CopyOptions; - CopyOptions.EnableClone = !m_NoClone; - - zen::CreateDirectories(ToPath.parent_path()); - if (zen::CopyFile(FromPath, ToPath, CopyOptions)) - { - ZEN_CONSOLE("Copy completed in {}", zen::NiceTimeSpanMs(Timer.GetElapsedTimeMs())); - } - else - { - throw std::runtime_error(fmt::format("Failed to copy '{}' to '{}'", FromPath, ToPath)); - } - } -} - -} // namespace zen |