diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-02-18 14:03:07 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-02-18 14:12:34 +0300 |
commit | f7386b97571e0207281f4504f45e13d4beb1c25b (patch) | |
tree | bb0a0ebb63b15f8a1e4841a9c2c5e884f44d8f7d /source | |
parent | d4e38d99b20209b3ddf1488f00a8fbc1a7b785e9 (diff) |
Fix T62612: Saving with "Remap Relative" makes ALL paths relative
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_bpath.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/bpath.c | 75 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 43 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 4 |
4 files changed, 101 insertions, 25 deletions
diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h index a11e8538897..eaf37f8fa6e 100644 --- a/source/blender/blenkernel/BKE_bpath.h +++ b/source/blender/blenkernel/BKE_bpath.h @@ -74,6 +74,10 @@ void BKE_bpath_missing_files_find(struct Main *bmain, const char *searchpath, struct ReportList *reports, const bool find_all); +void BKE_bpath_relative_rebase(struct Main *bmain, + const char *basedir_src, + const char *basedir_dst, + struct ReportList *reports); void BKE_bpath_relative_convert(struct Main *bmain, const char *basedir, struct ReportList *reports); diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 9bfa604a597..26e8bbde009 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -113,6 +113,81 @@ void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Rebase Relative Paths + * \{ */ + +typedef struct BPathRebase_Data { + const char *basedir_src; + const char *basedir_dst; + ReportList *reports; + + int count_tot; + int count_changed; + int count_failed; +} BPathRebase_Data; + +static bool bpath_relative_rebase_visit_cb(void *userdata, char *path_dst, const char *path_src) +{ + BPathRebase_Data *data = (BPathRebase_Data *)userdata; + + data->count_tot++; + + if (BLI_path_is_rel(path_src)) { + char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE]; + BLI_strncpy(filepath, path_src, FILE_MAX); + if (BLI_path_abs(filepath, data->basedir_src)) { + BLI_cleanup_path(NULL, filepath); + + /* This may fail, if so it's fine to leave absolute since the path is still valid. */ + BLI_path_rel(filepath, data->basedir_dst); + + BLI_strncpy(path_dst, filepath, FILE_MAX); + data->count_changed++; + return true; + } + else { + /* Failed to make relative path absolute. */ + BLI_assert(0); + BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src); + data->count_failed++; + return false; + } + return false; + } + else { + /* Absolute, leave this as-is. */ + return false; + } +} + +void BKE_bpath_relative_rebase(Main *bmain, + const char *basedir_src, + const char *basedir_dst, + ReportList *reports) +{ + BPathRebase_Data data = {NULL}; + const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY; + + BLI_assert(basedir_src[0] != '\0'); + BLI_assert(basedir_dst[0] != '\0'); + + data.basedir_src = basedir_src; + data.basedir_dst = basedir_dst; + data.reports = reports; + + BKE_bpath_traverse_main(bmain, bpath_relative_rebase_visit_cb, flag, (void *)&data); + + BKE_reportf(reports, + data.count_failed ? RPT_WARNING : RPT_INFO, + "Total files %d | Changed %d | Failed %d", + data.count_tot, + data.count_changed, + data.count_failed); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Make Paths Relative * \{ */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 643c2805487..7076ed906c1 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -4056,41 +4056,38 @@ bool BLO_write_file(Main *mainvar, return 0; } - /* check if we need to backup and restore paths */ - if (UNLIKELY((write_flags & G_FILE_RELATIVE_REMAP) && (G_FILE_SAVE_COPY & write_flags))) { - path_list_backup = BKE_bpath_list_backup(mainvar, path_list_flag); - } - - /* remapping of relative paths to new file location */ + /* Remapping of relative paths to new file location. */ if (write_flags & G_FILE_RELATIVE_REMAP) { - char dir1[FILE_MAX]; - char dir2[FILE_MAX]; - BLI_split_dir_part(filepath, dir1, sizeof(dir1)); - BLI_split_dir_part(mainvar->name, dir2, sizeof(dir2)); + char dir_src[FILE_MAX]; + char dir_dst[FILE_MAX]; + BLI_split_dir_part(mainvar->name, dir_src, sizeof(dir_src)); + BLI_split_dir_part(filepath, dir_dst, sizeof(dir_dst)); /* just in case there is some subtle difference */ - BLI_cleanup_dir(mainvar->name, dir1); - BLI_cleanup_dir(mainvar->name, dir2); + BLI_cleanup_dir(mainvar->name, dir_dst); + BLI_cleanup_dir(mainvar->name, dir_src); - if (G.relbase_valid && (BLI_path_cmp(dir1, dir2) == 0)) { + if (G.relbase_valid && (BLI_path_cmp(dir_dst, dir_src) == 0)) { + /* Saved to same path. Nothing to do. */ write_flags &= ~G_FILE_RELATIVE_REMAP; } else { + /* Check if we need to backup and restore paths. */ + if (UNLIKELY(G_FILE_SAVE_COPY & write_flags)) { + path_list_backup = BKE_bpath_list_backup(mainvar, path_list_flag); + } + if (G.relbase_valid) { - /* blend may not have been saved before. Tn this case - * we should not have any relative paths, but if there - * is somehow, an invalid or empty G_MAIN->name it will - * print an error, don't try make the absolute in this case. */ - BKE_bpath_absolute_convert(mainvar, BKE_main_blendfile_path_from_global(), NULL); + /* Saved, make relative paths relative to new location (if possible). */ + BKE_bpath_relative_rebase(mainvar, dir_src, dir_dst, NULL); + } + else { + /* Unsaved, make all relative. */ + BKE_bpath_relative_convert(mainvar, dir_dst, NULL); } } } - if (write_flags & G_FILE_RELATIVE_REMAP) { - /* note, making relative to something OTHER then G_MAIN->name */ - BKE_bpath_relative_convert(mainvar, filepath, NULL); - } - /* actual file writing */ const bool err = write_file_handle(mainvar, &ww, NULL, NULL, write_flags, thumb); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index ef31bcdb75e..eff5464c885 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -2668,7 +2668,7 @@ void WM_OT_save_as_mainfile(wmOperatorType *ot) "relative_remap", true, "Remap Relative", - "Make paths relative when saving to a different directory"); + "Remap relative paths when saving to a different directory"); prop = RNA_def_boolean( ot->srna, "copy", @@ -2740,7 +2740,7 @@ void WM_OT_save_mainfile(wmOperatorType *ot) "relative_remap", false, "Remap Relative", - "Make paths relative when saving to a different directory"); + "Remap relative paths when saving to a different directory"); prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); |