[Bf-blender-cvs] [f7386b97571] master: Fix T62612: Saving with "Remap Relative" makes ALL paths relative

Campbell Barton noreply at git.blender.org
Tue Feb 18 12:14:42 CET 2020


Commit: f7386b97571e0207281f4504f45e13d4beb1c25b
Author: Campbell Barton
Date:   Tue Feb 18 22:03:07 2020 +1100
Branches: master
https://developer.blender.org/rBf7386b97571e0207281f4504f45e13d4beb1c25b

Fix T62612: Saving with "Remap Relative" makes ALL paths relative

===================================================================

M	source/blender/blenkernel/BKE_bpath.h
M	source/blender/blenkernel/intern/bpath.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/windowmanager/intern/wm_files.c

===================================================================

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
@@ -112,6 +112,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);



More information about the Bf-blender-cvs mailing list