[nautilus] file-operations: Preserve mtime of non-empty directories on move



commit f29b4839187c0ab18dd2cf1fd99c7cb734cab8ff
Author: Maxim Mikityanskiy <maxtram95 gmail com>
Date:   Sun Aug 16 17:56:03 2020 +0300

    file-operations: Preserve mtime of non-empty directories on move
    
    Nautilus follows this algorithm when copying or moving directories:
    
    1. Create the destination directory.
    2. Copy/move the old directory contents recursively.
    3. g_file_copy_attributes from the old directory to the new.
    4. Delete the old directory.
    
    The issue is that when moving a non-empty directory, step 2 leads to
    modification of the old directory's mtime, so g_file_copy_attributes
    copies the attributes that were already lost at that point.
    
    This commit fixes it by splitting g_file_copy_attributes into two steps.
    It depends on glib!1449.
    
    Closes: gvfs#471
    Signed-off-by: Maxim Mikityanskiy <maxtram95 gmail com>

 meson.build                    |  2 +-
 src/nautilus-file-operations.c | 32 ++++++++++++++++++++++++++------
 2 files changed, 27 insertions(+), 7 deletions(-)
---
diff --git a/meson.build b/meson.build
index a5413d54c..3d9aaa340 100644
--- a/meson.build
+++ b/meson.build
@@ -93,7 +93,7 @@ pkgconfig = import('pkgconfig')
 ################
 # Dependencies #
 ################
-glib_ver = '>= 2.62.0'
+glib_ver = '>= 2.67.1'
 
 libgd = subproject(
   'libgd',
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index 3adf3b54c..43ed33941 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -4762,6 +4762,7 @@ copy_move_directory (CopyMoveJob   *copy_job,
                      gboolean      *skipped_file,
                      gboolean       readonly_source_fs)
 {
+    g_autoptr (GFileInfo) src_info = NULL;
     GFileInfo *info;
     GError *error;
     GFile *src_file;
@@ -4778,6 +4779,8 @@ copy_move_directory (CopyMoveJob   *copy_job,
 
     if (create_dest)
     {
+        g_autofree char *attrs_to_read = NULL;
+
         switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type))
         {
             case CREATE_DEST_DIR_RETRY:
@@ -4806,6 +4809,23 @@ copy_move_directory (CopyMoveJob   *copy_job,
         {
             g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (TRUE));
         }
+
+        flags = G_FILE_COPY_NOFOLLOW_SYMLINKS;
+        if (readonly_source_fs)
+        {
+            flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS;
+        }
+        if (copy_job->is_move)
+        {
+            flags |= G_FILE_COPY_ALL_METADATA;
+        }
+
+        /* Ignore errors here. Failure to copy metadata is not a hard error */
+        attrs_to_read = g_file_build_attribute_list_for_copy (*dest, flags, job->cancellable, NULL);
+        if (attrs_to_read != NULL)
+        {
+            src_info = g_file_query_info (src, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 
job->cancellable, NULL);
+        }
     }
 
     local_skipped_file = FALSE;
@@ -4971,14 +4991,14 @@ retry:
         }
     }
 
-    if (create_dest)
+    if (src_info != NULL)
     {
-        flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS
-                : G_FILE_COPY_NOFOLLOW_SYMLINKS;
         /* Ignore errors here. Failure to copy metadata is not a hard error */
-        g_file_copy_attributes (src, *dest,
-                                flags,
-                                job->cancellable, NULL);
+        g_file_set_attributes_from_info (*dest,
+                                         src_info,
+                                         G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                         job->cancellable,
+                                         NULL);
     }
 
     if (!job_aborted (job) && copy_job->is_move &&


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]