[Bf-blender-cvs] [8dbd406ea0f] master: WM: various changes to file writing behavior

Campbell Barton noreply at git.blender.org
Thu Dec 16 06:29:28 CET 2021


Commit: 8dbd406ea0f495b3d404a7433a32b4781953e55a
Author: Campbell Barton
Date:   Thu Dec 16 16:17:28 2021 +1100
Branches: master
https://developer.blender.org/rB8dbd406ea0f495b3d404a7433a32b4781953e55a

WM: various changes to file writing behavior

Saving with only a filename (from Python) wasn't being prevented,
while it would successfully write the file to the working-directory,
path remapping and setting relative paths wouldn't work afterwards
as `Main.filepath` would have no directory component.

Disallow this since it's a corner case which only ever occurs
when path names without any directories are used from Python,
the overhead of expanding the working-directory for all data saving
operations isn't worthwhile.

The following changes have been made:

- bpy.ops.wm.save_mainfile() without a filepath argument
  fails & reports and error when the file hasn't been saved.

  Previously it would write to "untitled.blend" and set the
  `G.main->filepath` to this as well.

- bpy.ops.wm.save_mainfile(filepath="untitled.blend")
  fails & reports and error as the filename has no directory component.

- `BLI_path_is_abs_from_cwd` was added to check if the path would
  attempt to expand to the CWD.

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

M	source/blender/blenlib/BLI_path_util.h
M	source/blender/blenlib/intern/path_util.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/windowmanager/intern/wm_files.c

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

diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 9e2970f6013..3cffecae187 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -323,9 +323,15 @@ void BLI_path_frame_strip(char *path, char *ext) ATTR_NONNULL();
  * Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
  */
 bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
+/**
+ * Checks for a relative path (ignoring Blender's "//") prefix
+ * (unlike `!BLI_path_is_rel(path)`).
+ * When false, #BLI_path_abs_from_cwd would expand the absolute path.
+ */
+bool BLI_path_is_abs_from_cwd(const char *path) ATTR_NONNULL();
 /**
  * Checks for relative path, expanding them relative to the current working directory.
- * Returns true if the expansion was performed.
+ * \returns true if the expansion was performed.
  *
  * \note Should only be called with command line paths.
  * This is _not_ something Blender's internal paths support, instead they use the "//" prefix.
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index c40eed711f5..de71188abfe 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1002,25 +1002,30 @@ bool BLI_path_abs(char *path, const char *basepath)
   return wasrelative;
 }
 
-bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
+bool BLI_path_is_abs_from_cwd(const char *path)
 {
-#ifdef DEBUG_STRSIZE
-  memset(path, 0xff, sizeof(*path) * maxlen);
-#endif
-  bool wasrelative = true;
-  const int filelen = strlen(path);
+  bool is_abs = false;
+  const int path_len_clamp = BLI_strnlen(path, 3);
 
 #ifdef WIN32
-  if ((filelen >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) {
-    wasrelative = false;
+  if ((ppath_len_clamp >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) {
+    is_abs = true;
   }
 #else
-  if (filelen >= 2 && path[0] == '/') {
-    wasrelative = false;
+  if (path_len_clamp >= 2 && path[0] == '/') {
+    is_abs = true;
   }
 #endif
+  return is_abs;
+}
 
-  if (wasrelative) {
+bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
+{
+#ifdef DEBUG_STRSIZE
+  memset(path, 0xff, sizeof(*path) * maxlen);
+#endif
+
+  if (!BLI_path_is_abs_from_cwd(path)) {
     char cwd[FILE_MAX];
     /* in case the full path to the blend isn't used */
     if (BLI_current_working_dir(cwd, sizeof(cwd))) {
@@ -1031,9 +1036,10 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
     else {
       printf("Could not get the current working directory - $PWD for an unknown reason.\n");
     }
+    return true;
   }
 
-  return wasrelative;
+  return false;
 }
 
 #ifdef _WIN32
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index e0ff70d4b49..aa3eef4b475 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1319,6 +1319,7 @@ bool BLO_write_file(Main *mainvar,
                     ReportList *reports)
 {
   BLI_assert(!BLI_path_is_rel(filepath));
+  BLI_assert(BLI_path_is_abs_from_cwd(filepath));
 
   char tempname[FILE_MAX + 1];
   WriteWrap ww;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 7ac9395e16c..1d3fa158ac1 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -3067,12 +3067,32 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
                                              BLO_WRITE_PATH_REMAP_NONE;
   save_set_compress(op);
 
-  if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+  const bool is_filepath_set = RNA_struct_property_is_set(op->ptr, "filepath");
+  if (is_filepath_set) {
     RNA_string_get(op->ptr, "filepath", path);
   }
   else {
-    BLI_strncpy(path, BKE_main_blendfile_path(bmain), FILE_MAX);
-    wm_filepath_default(bmain, path);
+    STRNCPY(path, BKE_main_blendfile_path(bmain));
+  }
+
+  if (path[0] == '\0') {
+    BKE_report(op->reports,
+               RPT_ERROR,
+               "Unable to save an unsaved file with an empty or unset \"filepath\" property");
+    return OPERATOR_CANCELLED;
+  }
+
+  /* NOTE(@campbellbarton): only check this for file-path properties so saving an already
+   * saved file never fails with an error.
+   * Even though this should never happen, there may be some corner case where a malformed
+   * path is stored in `G.main->filepath`: when the file path is initialized from recovering
+   * a blend file - for example, so in this case failing to save isn't ideal. */
+  if (is_filepath_set && !BLI_path_is_abs_from_cwd(path)) {
+    BKE_reportf(op->reports,
+                RPT_ERROR,
+                "The \"filepath\" property was not an absolute path: \"%s\"",
+                path);
+    return OPERATOR_CANCELLED;
   }
 
   const int fileflags_orig = G.fileflags;



More information about the Bf-blender-cvs mailing list