diff options
Diffstat (limited to 'source/blender/io/common/intern/path_util.cc')
-rw-r--r-- | source/blender/io/common/intern/path_util.cc | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/source/blender/io/common/intern/path_util.cc b/source/blender/io/common/intern/path_util.cc new file mode 100644 index 00000000000..2b9a1d67b44 --- /dev/null +++ b/source/blender/io/common/intern/path_util.cc @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "IO_path_util.hh" + +#include "BLI_fileops.h" +#include "BLI_path_util.h" + +namespace blender::io { + +std::string path_reference(StringRefNull filepath, + StringRefNull base_src, + StringRefNull base_dst, + ePathReferenceMode mode, + Set<std::pair<std::string, std::string>> *copy_set) +{ + const bool is_relative = BLI_path_is_rel(filepath.c_str()); + char filepath_abs[PATH_MAX]; + BLI_strncpy(filepath_abs, filepath.c_str(), PATH_MAX); + BLI_path_abs(filepath_abs, base_src.c_str()); + BLI_path_normalize(nullptr, filepath_abs); + + /* Figure out final mode to be used. */ + if (mode == PATH_REFERENCE_MATCH) { + mode = is_relative ? PATH_REFERENCE_RELATIVE : PATH_REFERENCE_ABSOLUTE; + } + else if (mode == PATH_REFERENCE_AUTO) { + mode = BLI_path_contains(base_dst.c_str(), filepath_abs) ? PATH_REFERENCE_RELATIVE : + PATH_REFERENCE_ABSOLUTE; + } + else if (mode == PATH_REFERENCE_COPY) { + char filepath_cpy[PATH_MAX]; + BLI_path_join(filepath_cpy, PATH_MAX, base_dst.c_str(), BLI_path_basename(filepath_abs), nullptr); + copy_set->add(std::make_pair(filepath_abs, filepath_cpy)); + BLI_strncpy(filepath_abs, filepath_cpy, PATH_MAX); + mode = PATH_REFERENCE_RELATIVE; + } + + /* Now we know the final path mode. */ + if (mode == PATH_REFERENCE_ABSOLUTE) { + return filepath_abs; + } + else if (mode == PATH_REFERENCE_RELATIVE) { + char rel_path[PATH_MAX]; + BLI_strncpy(rel_path, filepath_abs, PATH_MAX); + BLI_path_rel(rel_path, base_dst.c_str()); + /* Can't always find relative path (e.g. between different drives). */ + if (!BLI_path_is_rel(rel_path)) { + return filepath_abs; + } + return rel_path + 2; /* Skip blender's internal "//" prefix. */ + } + else if (mode == PATH_REFERENCE_STRIP) { + return BLI_path_basename(filepath_abs); + } + BLI_assert_msg(false, "Invalid path reference mode"); + return filepath_abs; +} + +void path_reference_copy(const Set<std::pair<std::string, std::string>> ©_set) +{ + for (const auto © : copy_set) { + const char *src = copy.first.c_str(); + const char *dst = copy.second.c_str(); + if (!BLI_exists(src)) { + fprintf(stderr, "Missing source file '%s', not copying\n", src); + continue; + } + if (0 == BLI_path_cmp_normalized(src, dst)) { + continue; /* Source and dest are the same. */ + } + if (!BLI_make_existing_file(dst)) { + fprintf(stderr, "Can't make directory for '%s', not copying\n", dst); + continue; + } + if (!BLI_copy(src, dst)) { + fprintf(stderr, "Can't copy '%s' to '%s'\n", src, dst); + continue; + } + } +} + +} // namespace blender::io |