Browse Source

Don't calculate totals for move operation on single file.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Andrew Borodin 7 years ago
parent
commit
3ba4417c18
1 changed files with 310 additions and 263 deletions
  1. 310 263
      src/filemanager/file.c

+ 310 - 263
src/filemanager/file.c

@@ -609,6 +609,118 @@ do_compute_dir_size (const vfs_path_t * dirname_vpath, dirsize_status_msg_t * ds
     return ret;
 }
 
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * panel_compute_totals:
+ *
+ * compute the number of files and the number of bytes
+ * used up by the whole selection, recursing directories
+ * as required.  In addition, it checks to see if it will
+ * overwrite any files by doing the copy.
+ */
+
+static FileProgressStatus
+panel_compute_totals (const WPanel * panel, dirsize_status_msg_t * sm, size_t * ret_count,
+                      uintmax_t * ret_total, gboolean compute_symlinks)
+{
+    int i;
+    size_t dir_count = 0;
+
+    for (i = 0; i < panel->dir.len; i++)
+    {
+        struct stat *s;
+
+        if (!panel->dir.list[i].f.marked)
+            continue;
+
+        s = &panel->dir.list[i].st;
+
+        if (S_ISDIR (s->st_mode))
+        {
+            vfs_path_t *p;
+            FileProgressStatus status;
+
+            p = vfs_path_append_new (panel->cwd_vpath, panel->dir.list[i].fname, (char *) NULL);
+            status = compute_dir_size (p, sm, &dir_count, ret_count, ret_total, compute_symlinks);
+            vfs_path_free (p);
+
+            if (status != FILE_CONT)
+                return status;
+        }
+        else
+        {
+            (*ret_count)++;
+            *ret_total += (uintmax_t) s->st_size;
+        }
+    }
+
+    return FILE_CONT;
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+/** Initialize variables for progress bars */
+static FileProgressStatus
+panel_operate_init_totals (const WPanel * panel, const vfs_path_t * source,
+                           const struct stat *source_stat, file_op_context_t * ctx,
+                           filegui_dialog_type_t dialog_type)
+{
+    FileProgressStatus status;
+
+#ifdef ENABLE_BACKGROUND
+    if (mc_global.we_are_background)
+        return FILE_CONT;
+#endif
+
+    if (verbose && file_op_compute_totals)
+    {
+        dirsize_status_msg_t dsm;
+
+        memset (&dsm, 0, sizeof (dsm));
+        dsm.allow_skip = TRUE;
+        status_msg_init (STATUS_MSG (&dsm), _("Directory scanning"), 0, dirsize_status_init_cb,
+                         dirsize_status_update_cb, dirsize_status_deinit_cb);
+
+        ctx->progress_count = 0;
+        ctx->progress_bytes = 0;
+
+        if (source == NULL)
+            status = panel_compute_totals (panel, &dsm, &ctx->progress_count, &ctx->progress_bytes,
+                                           ctx->follow_links);
+        else if (S_ISDIR (source_stat->st_mode))
+        {
+            size_t dir_count = 0;
+
+            status = compute_dir_size (source, &dsm, &dir_count, &ctx->progress_count,
+                                       &ctx->progress_bytes, ctx->follow_links);
+        }
+        else
+        {
+            ctx->progress_count++;
+            ctx->progress_bytes += (uintmax_t) source_stat->st_size;
+            status = FILE_CONT;
+        }
+
+        status_msg_deinit (STATUS_MSG (&dsm));
+
+        ctx->progress_totals_computed = (status == FILE_CONT);
+
+        if (status == FILE_SKIP)
+            status = FILE_CONT;
+    }
+    else
+    {
+        status = FILE_CONT;
+        ctx->progress_count = panel->marked;
+        ctx->progress_bytes = panel->total;
+        ctx->progress_totals_computed = FALSE;
+    }
+
+    file_op_context_create_ui (ctx, TRUE, dialog_type);
+
+    return status;
+}
+
 /* --------------------------------------------------------------------------------------------- */
 
 static FileProgressStatus
@@ -976,9 +1088,21 @@ try_remove_file (file_op_context_t * ctx, const vfs_path_t * vpath, FileProgress
 /* --------------------------------------------------------------------------------------------- */
 
 /* {{{ Move routines */
+
+/**
+ * Move single file or one of many files from one location to another.
+ *
+ * @panel pointer to panel in case of single file, NULL otherwise
+ * @tctx file operation total context object
+ * @ctx file operation context object
+ * @s source file name
+ * @d destination file name
+ *
+ * @return operation result
+ */
 static FileProgressStatus
-move_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const char *s,
-                const char *d)
+move_file_file (const WPanel * panel, file_op_total_context_t * tctx, file_op_context_t * ctx,
+                const char *s, const char *d)
 {
     struct stat src_stats, dst_stats;
     FileProgressStatus return_status = FILE_CONT;
@@ -992,6 +1116,7 @@ move_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const c
     file_progress_show_source (ctx, src_vpath);
     file_progress_show_target (ctx, dst_vpath);
 
+    /* FIXME: do we really need to check buttons in case of single file? */
     if (check_progress_buttons (ctx) == FILE_ABORT)
     {
         return_status = FILE_ABORT;
@@ -1050,6 +1175,7 @@ move_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const c
 
         if (mc_rename (src_vpath, dst_vpath) == 0)
         {
+            /* FIXME: do we really need to update progress in case of single file? */
             return_status = progress_update_one (tctx, ctx, src_stats.st_size);
             goto ret;
         }
@@ -1079,7 +1205,17 @@ move_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const c
     }
 #endif
 
-    /* Failed because filesystem boundary -> copy the file instead */
+    /* Failed rename -> copy the file instead */
+    if (panel != NULL)
+    {
+        /* In case of single file, calculate totals. In case of many files,
+           totals are calcuated already. */
+        return_status =
+            panel_operate_init_totals (panel, src_vpath, &src_stats, ctx, FILEGUI_DIALOG_ONE_ITEM);
+        if (return_status != FILE_CONT)
+            goto ret;
+    }
+
     old_ask_overwrite = tctx->ask_overwrite;
     tctx->ask_overwrite = FALSE;
     return_status = copy_file_file (tctx, ctx, s, d);
@@ -1089,16 +1225,22 @@ move_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const c
 
     copy_done = TRUE;
 
-    file_progress_show_source (ctx, NULL);
-    file_progress_show (ctx, 0, 0, "", FALSE);
+    /* FIXME: there is no need to update progress and check buttons
+       at the finish of single file operation. */
+    if (panel == NULL)
+    {
+        file_progress_show_source (ctx, NULL);
+        file_progress_show (ctx, 0, 0, "", FALSE);
+
+        return_status = check_progress_buttons (ctx);
+        if (return_status != FILE_CONT)
+            goto ret;
+    }
 
-    return_status = check_progress_buttons (ctx);
-    if (return_status != FILE_CONT)
-        goto ret;
     mc_refresh ();
 
   retry_src_remove:
-    if (!try_remove_file (ctx, src_vpath, &return_status))
+    if (!try_remove_file (ctx, src_vpath, &return_status) && panel == NULL)
         goto ret;
 
     if (!copy_done)
@@ -1307,6 +1449,157 @@ erase_dir_after_copy (file_op_total_context_t * tctx, file_op_context_t * ctx,
 
 /* --------------------------------------------------------------------------------------------- */
 
+/**
+ * Move single directory or one of many directories from one location to another.
+ *
+ * @panel pointer to panel in case of single directory, NULL otherwise
+ * @tctx file operation total context object
+ * @ctx file operation context object
+ * @s source directory name
+ * @d destination directory name
+ *
+ * @return operation result
+ */
+static FileProgressStatus
+do_move_dir_dir (const WPanel * panel, file_op_total_context_t * tctx, file_op_context_t * ctx,
+                 const char *s, const char *d)
+{
+    struct stat sbuf, dbuf;
+    FileProgressStatus return_status = FILE_CONT;
+    gboolean move_over = FALSE;
+    gboolean dstat_ok;
+    vfs_path_t *src_vpath, *dst_vpath;
+
+    src_vpath = vfs_path_from_str (s);
+    dst_vpath = vfs_path_from_str (d);
+
+    file_progress_show_source (ctx, src_vpath);
+    file_progress_show_target (ctx, dst_vpath);
+
+    /* FIXME: do we really need to check buttons in case of single directory? */
+    if (panel != NULL && check_progress_buttons (ctx) == FILE_ABORT)
+    {
+        return_status = FILE_ABORT;
+        goto ret_fast;
+    }
+
+    mc_refresh ();
+
+    mc_stat (src_vpath, &sbuf);
+
+    dstat_ok = (mc_stat (dst_vpath, &dbuf) == 0);
+
+    if (dstat_ok && check_same_file (s, &sbuf, d, &dbuf, &return_status))
+        goto ret_fast;
+
+    if (!dstat_ok)
+        ;                       /* destination doesn't exist */
+    else if (!ctx->dive_into_subdirs)
+        move_over = TRUE;
+    else
+    {
+        vfs_path_t *tmp;
+
+        tmp = dst_vpath;
+        dst_vpath = vfs_path_append_new (dst_vpath, x_basename (s), (char *) NULL);
+        vfs_path_free (tmp);
+    }
+
+    d = vfs_path_as_str (dst_vpath);
+
+    /* Check if the user inputted an existing dir */
+  retry_dst_stat:
+    if (mc_stat (dst_vpath, &dbuf) == 0)
+    {
+        if (move_over)
+        {
+            return_status = copy_dir_dir (tctx, ctx, s, d, FALSE, TRUE, TRUE, NULL);
+
+            if (return_status != FILE_CONT)
+                goto ret;
+            goto oktoret;
+        }
+        else if (ctx->skip_all)
+            return_status = FILE_SKIPALL;
+        else
+        {
+            if (S_ISDIR (dbuf.st_mode))
+                return_status = file_error (_("Cannot overwrite directory \"%s\"\n%s"), d);
+            else
+                return_status = file_error (_("Cannot overwrite file \"%s\"\n%s"), d);
+            if (return_status == FILE_SKIPALL)
+                ctx->skip_all = TRUE;
+            if (return_status == FILE_RETRY)
+                goto retry_dst_stat;
+        }
+
+        goto ret_fast;
+    }
+
+  retry_rename:
+    if (mc_rename (src_vpath, dst_vpath) == 0)
+    {
+        return_status = FILE_CONT;
+        goto ret;
+    }
+
+    if (errno != EXDEV)
+    {
+        if (!ctx->skip_all)
+        {
+            return_status = files_error (_("Cannot move directory \"%s\" to \"%s\"\n%s"), s, d);
+            if (return_status == FILE_SKIPALL)
+                ctx->skip_all = TRUE;
+            if (return_status == FILE_RETRY)
+                goto retry_rename;
+        }
+        goto ret;
+    }
+
+    /* Failed because of filesystem boundary -> copy dir instead */
+    if (panel != NULL)
+    {
+        /* In case of single directory, calculate totals. In case of many directories,
+           totals are calcuated already. */
+        return_status =
+            panel_operate_init_totals (panel, src_vpath, &sbuf, ctx, FILEGUI_DIALOG_ONE_ITEM);
+        if (return_status != FILE_CONT)
+            goto ret;
+    }
+
+    return_status = copy_dir_dir (tctx, ctx, s, d, FALSE, FALSE, TRUE, NULL);
+
+    if (return_status != FILE_CONT)
+        goto ret;
+
+  oktoret:
+    /* FIXME: there is no need to update progress and check buttons
+       at the finish of single directory operation. */
+    if (panel == NULL)
+    {
+        file_progress_show_source (ctx, NULL);
+        file_progress_show_target (ctx, NULL);
+        file_progress_show (ctx, 0, 0, "", FALSE);
+
+        return_status = check_progress_buttons (ctx);
+        if (return_status != FILE_CONT)
+            goto ret;
+    }
+
+    mc_refresh ();
+
+    erase_dir_after_copy (tctx, ctx, src_vpath, &return_status);
+
+  ret:
+    erase_list = free_linklist (erase_list);
+  ret_fast:
+    vfs_path_free (src_vpath);
+    vfs_path_free (dst_vpath);
+    return return_status;
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
 /* {{{ Panel operate routines */
 
 /**
@@ -1388,118 +1681,6 @@ check_single_entry (const WPanel * panel, gboolean force_single, struct stat *sr
     return ok ? source : NULL;
 }
 
-/* --------------------------------------------------------------------------------------------- */
-/**
- * panel_compute_totals:
- *
- * compute the number of files and the number of bytes
- * used up by the whole selection, recursing directories
- * as required.  In addition, it checks to see if it will
- * overwrite any files by doing the copy.
- */
-
-static FileProgressStatus
-panel_compute_totals (const WPanel * panel, dirsize_status_msg_t * sm, size_t * ret_count,
-                      uintmax_t * ret_total, gboolean compute_symlinks)
-{
-    int i;
-    size_t dir_count = 0;
-
-    for (i = 0; i < panel->dir.len; i++)
-    {
-        struct stat *s;
-
-        if (!panel->dir.list[i].f.marked)
-            continue;
-
-        s = &panel->dir.list[i].st;
-
-        if (S_ISDIR (s->st_mode))
-        {
-            vfs_path_t *p;
-            FileProgressStatus status;
-
-            p = vfs_path_append_new (panel->cwd_vpath, panel->dir.list[i].fname, (char *) NULL);
-            status = compute_dir_size (p, sm, &dir_count, ret_count, ret_total, compute_symlinks);
-            vfs_path_free (p);
-
-            if (status != FILE_CONT)
-                return status;
-        }
-        else
-        {
-            (*ret_count)++;
-            *ret_total += (uintmax_t) s->st_size;
-        }
-    }
-
-    return FILE_CONT;
-}
-
-/* --------------------------------------------------------------------------------------------- */
-
-/** Initialize variables for progress bars */
-static FileProgressStatus
-panel_operate_init_totals (const WPanel * panel, const vfs_path_t * source,
-                           const struct stat *source_stat, file_op_context_t * ctx,
-                           filegui_dialog_type_t dialog_type)
-{
-    FileProgressStatus status;
-
-#ifdef ENABLE_BACKGROUND
-    if (mc_global.we_are_background)
-        return FILE_CONT;
-#endif
-
-    if (verbose && file_op_compute_totals)
-    {
-        dirsize_status_msg_t dsm;
-
-        memset (&dsm, 0, sizeof (dsm));
-        dsm.allow_skip = TRUE;
-        status_msg_init (STATUS_MSG (&dsm), _("Directory scanning"), 0, dirsize_status_init_cb,
-                         dirsize_status_update_cb, dirsize_status_deinit_cb);
-
-        ctx->progress_count = 0;
-        ctx->progress_bytes = 0;
-
-        if (source == NULL)
-            status = panel_compute_totals (panel, &dsm, &ctx->progress_count, &ctx->progress_bytes,
-                                           ctx->follow_links);
-        else if (S_ISDIR (source_stat->st_mode))
-        {
-            size_t dir_count = 0;
-
-            status = compute_dir_size (source, &dsm, &dir_count, &ctx->progress_count,
-                                       &ctx->progress_bytes, ctx->follow_links);
-        }
-        else
-        {
-            ctx->progress_count++;
-            ctx->progress_bytes += (uintmax_t) source_stat->st_size;
-            status = FILE_CONT;
-        }
-
-        status_msg_deinit (STATUS_MSG (&dsm));
-
-        ctx->progress_totals_computed = (status == FILE_CONT);
-
-        if (status == FILE_SKIP)
-            status = FILE_CONT;
-    }
-    else
-    {
-        status = FILE_CONT;
-        ctx->progress_count = panel->marked;
-        ctx->progress_bytes = panel->total;
-        ctx->progress_totals_computed = FALSE;
-    }
-
-    file_op_context_create_ui (ctx, TRUE, dialog_type);
-
-    return status;
-}
-
 /* --------------------------------------------------------------------------------------------- */
 /**
  * Generate user prompt for panel operation.
@@ -1744,32 +1925,11 @@ operate_single_file (const WPanel * panel, FileOperation operation, file_op_tota
                 break;
 
             case OP_MOVE:
-                {
-                    vfs_path_t *dest_vpath;
-
-                    dest_vpath = vfs_path_from_str (dest);
-
-                    /* try rename */
-                    if (mc_rename (src_vpath, dest_vpath) == 0)
-                        value = FILE_CONT;
-                    else
-                    {
-                        /* copy + delete */
-                        value =
-                            panel_operate_init_totals (panel, src_vpath, src_stat, ctx,
-                                                       dialog_type);
-                        if (value == FILE_CONT)
-                        {
-                            if (is_file)
-                                value = move_file_file (tctx, ctx, src, dest);
-                            else
-                                value = move_dir_dir (tctx, ctx, src, dest);
-                        }
-                    }
-
-                    vfs_path_free (dest_vpath);
-                    break;
-                }
+                if (is_file)
+                    value = move_file_file (panel, tctx, ctx, src, dest);
+                else
+                    value = do_move_dir_dir (panel, tctx, ctx, src, dest);
+                break;
 
             default:
                 /* Unknown file operation */
@@ -1844,9 +2004,9 @@ operate_one_file (const WPanel * panel, FileOperation operation, file_op_total_c
 
             case OP_MOVE:
                 if (is_file)
-                    value = move_file_file (tctx, ctx, src, dest);
+                    value = move_file_file (NULL, tctx, ctx, src, dest);
                 else
-                    value = move_dir_dir (tctx, ctx, src, dest);
+                    value = do_move_dir_dir (NULL, tctx, ctx, src, dest);
                 break;
 
             default:
@@ -2701,120 +2861,7 @@ copy_dir_dir (file_op_total_context_t * tctx, file_op_context_t * ctx, const cha
 FileProgressStatus
 move_dir_dir (file_op_total_context_t * tctx, file_op_context_t * ctx, const char *s, const char *d)
 {
-    struct stat sbuf, dbuf;
-    FileProgressStatus return_status = FILE_CONT;
-    gboolean move_over = FALSE;
-    gboolean dstat_ok;
-    vfs_path_t *src_vpath, *dst_vpath;
-
-    src_vpath = vfs_path_from_str (s);
-    dst_vpath = vfs_path_from_str (d);
-
-    file_progress_show_source (ctx, src_vpath);
-    file_progress_show_target (ctx, dst_vpath);
-
-    if (check_progress_buttons (ctx) == FILE_ABORT)
-    {
-        return_status = FILE_ABORT;
-        goto ret_fast;
-    }
-
-    mc_refresh ();
-
-    mc_stat (src_vpath, &sbuf);
-
-    dstat_ok = (mc_stat (dst_vpath, &dbuf) == 0);
-
-    if (dstat_ok && check_same_file (s, &sbuf, d, &dbuf, &return_status))
-        goto ret_fast;
-
-    if (!dstat_ok)
-        ;                       /* destination doesn't exist */
-    else if (!ctx->dive_into_subdirs)
-        move_over = TRUE;
-    else
-    {
-        vfs_path_t *tmp;
-
-        tmp = dst_vpath;
-        dst_vpath = vfs_path_append_new (dst_vpath, x_basename (s), (char *) NULL);
-        vfs_path_free (tmp);
-    }
-
-    d = vfs_path_as_str (dst_vpath);
-
-    /* Check if the user inputted an existing dir */
-  retry_dst_stat:
-    if (mc_stat (dst_vpath, &dbuf) == 0)
-    {
-        if (move_over)
-        {
-            return_status = copy_dir_dir (tctx, ctx, s, d, FALSE, TRUE, TRUE, NULL);
-
-            if (return_status != FILE_CONT)
-                goto ret;
-            goto oktoret;
-        }
-        else if (ctx->skip_all)
-            return_status = FILE_SKIPALL;
-        else
-        {
-            if (S_ISDIR (dbuf.st_mode))
-                return_status = file_error (_("Cannot overwrite directory \"%s\"\n%s"), d);
-            else
-                return_status = file_error (_("Cannot overwrite file \"%s\"\n%s"), d);
-            if (return_status == FILE_SKIPALL)
-                ctx->skip_all = TRUE;
-            if (return_status == FILE_RETRY)
-                goto retry_dst_stat;
-        }
-
-        goto ret_fast;
-    }
-
-  retry_rename:
-    if (mc_rename (src_vpath, dst_vpath) == 0)
-    {
-        return_status = FILE_CONT;
-        goto ret;
-    }
-
-    if (errno != EXDEV)
-    {
-        if (!ctx->skip_all)
-        {
-            return_status = files_error (_("Cannot move directory \"%s\" to \"%s\"\n%s"), s, d);
-            if (return_status == FILE_SKIPALL)
-                ctx->skip_all = TRUE;
-            if (return_status == FILE_RETRY)
-                goto retry_rename;
-        }
-        goto ret;
-    }
-    /* Failed because of filesystem boundary -> copy dir instead */
-    return_status = copy_dir_dir (tctx, ctx, s, d, FALSE, FALSE, TRUE, NULL);
-
-    if (return_status != FILE_CONT)
-        goto ret;
-  oktoret:
-    file_progress_show_source (ctx, NULL);
-    file_progress_show_target (ctx, NULL);
-    file_progress_show (ctx, 0, 0, "", FALSE);
-
-    return_status = check_progress_buttons (ctx);
-    if (return_status != FILE_CONT)
-        goto ret;
-
-    mc_refresh ();
-
-    erase_dir_after_copy (tctx, ctx, src_vpath, &return_status);
-
-  ret:
-    erase_list = free_linklist (erase_list);
-  ret_fast:
-    vfs_path_free (src_vpath);
-    vfs_path_free (dst_vpath);
-    return return_status;
+    return do_move_dir_dir (NULL, tctx, ctx, s, d);
 }
 
 /* }}} */