Issue #332 Rename function can delete files
[geeqie.git] / src / filedata.c
index 6adafc2..9515d2b 100644 (file)
 
 #include <errno.h>
 
+#ifdef DEBUG_FILEDATA
+gint global_file_data_count = 0;
+#endif
+
 static GHashTable *file_data_pool = NULL;
 static GHashTable *file_data_planned_change_hash = NULL;
 
@@ -161,6 +165,7 @@ static gboolean file_data_check_changed_single_file(FileData *fd, struct stat *s
                {
                fd->size = st->st_size;
                fd->date = st->st_mtime;
+               fd->cdate = st->st_ctime;
                fd->mode = st->st_mode;
                if (fd->thumb_pixbuf) g_object_unref(fd->thumb_pixbuf);
                fd->thumb_pixbuf = NULL;
@@ -383,9 +388,14 @@ static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean
                }
 
        fd = g_new0(FileData, 1);
+#ifdef DEBUG_FILEDATA
+       global_file_data_count++;
+       DEBUG_2("file data count++: %d", global_file_data_count);
+#endif
 
        fd->size = st->st_size;
        fd->date = st->st_mtime;
+       fd->cdate = st->st_ctime;
        fd->mode = st->st_mode;
        fd->ref = 1;
        fd->magick = FD_MAGICK;
@@ -406,6 +416,27 @@ static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolea
        return ret;
 }
 
+FileData *file_data_new_simple(const gchar *path_utf8)
+{
+       struct stat st;
+       FileData *fd;
+
+       if (!stat_utf8(path_utf8, &st))
+               {
+               st.st_size = 0;
+               st.st_mtime = 0;
+               }
+
+       fd = g_hash_table_lookup(file_data_pool, path_utf8);
+       if (!fd) fd = file_data_new(path_utf8, &st, TRUE);
+       if (fd)
+               {
+               file_data_ref(fd);
+               }
+
+       return fd;
+}
+
 void init_exif_time_data(GList *files)
 {
        FileData *file;
@@ -534,6 +565,11 @@ static void file_data_free(FileData *fd)
        g_assert(fd->ref == 0);
        g_assert(!fd->locked);
 
+#ifdef DEBUG_FILEDATA
+       global_file_data_count--;
+       DEBUG_2("file data count--: %d", global_file_data_count);
+#endif
+
        metadata_cache_free(fd);
        g_hash_table_remove(file_data_pool, fd->original_path);
 
@@ -963,6 +999,11 @@ gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
                        if (fa->date > fb->date) return 1;
                        /* fall back to name */
                        break;
+               case SORT_CTIME:
+                       if (fa->cdate < fb->cdate) return -1;
+                       if (fa->cdate > fb->cdate) return 1;
+                       /* fall back to name */
+                       break;
                case SORT_EXIFTIME:
                        if (fa->exifdate < fb->exifdate) return -1;
                        if (fa->exifdate > fb->exifdate) return 1;
@@ -1249,8 +1290,11 @@ FileData *file_data_new_group(const gchar *path_utf8)
        filelist_read_real(dir, &files, NULL, TRUE);
 
        fd = g_hash_table_lookup(file_data_pool, path_utf8);
-       g_assert(fd);
-       file_data_ref(fd);
+       if (!fd) fd = file_data_new(path_utf8, &st, TRUE);
+       if (fd)
+               {
+               file_data_ref(fd);
+               }
 
        filelist_free(files);
        g_free(dir);
@@ -2140,10 +2184,12 @@ gboolean file_data_sc_update_ci_unspecified_list(GList *fd_list, const gchar *de
  * it should detect all possible problems with the planned operation
  */
 
-gint file_data_verify_ci(FileData *fd)
+gint file_data_verify_ci(FileData *fd, GList *list)
 {
        gint ret = CHANGE_OK;
        gchar *dir;
+       GList *work = NULL;
+       FileData *fd1 = NULL;
 
        if (!fd->change)
                {
@@ -2353,6 +2399,26 @@ gint file_data_verify_ci(FileData *fd)
                g_free(dest_dir);
                }
 
+       /* During a rename operation, check if another planned destination file has
+        * the same filename
+        */
+       if(fd->change->type == FILEDATA_CHANGE_RENAME)
+               {
+               work = list;
+               while (work)
+                       {
+                       fd1 = work->data;
+                       work = work->next;
+                       if (fd1 != NULL && fd != fd1 )
+                               {
+                               if (!strcmp(fd->change->dest, fd1->change->dest))
+                                       {
+                                       ret |= CHANGE_DUPLICATE_DEST;
+                                       }
+                               }
+                       }
+               }
+
        fd->change->error = ret;
        if (ret == 0) DEBUG_1("Change checked: OK: %s", fd->path);
 
@@ -2361,19 +2427,19 @@ gint file_data_verify_ci(FileData *fd)
 }
 
 
-gint file_data_sc_verify_ci(FileData *fd)
+gint file_data_sc_verify_ci(FileData *fd, GList *list)
 {
        GList *work;
        gint ret;
 
-       ret = file_data_verify_ci(fd);
+       ret = file_data_verify_ci(fd, list);
 
        work = fd->sidecar_files;
        while (work)
                {
                FileData *sfd = work->data;
 
-               ret |= file_data_verify_ci(sfd);
+               ret |= file_data_verify_ci(sfd, list);
                work = work->next;
                }
 
@@ -2456,6 +2522,12 @@ gchar *file_data_get_error_string(gint error)
                g_string_append(result, _("there are unsaved metadata changes for the file"));
                }
 
+       if (error & CHANGE_DUPLICATE_DEST)
+               {
+               if (result->len > 0) g_string_append(result, ", ");
+               g_string_append(result, _("another destination file has the same filename"));
+               }
+
        return g_string_free(result, FALSE);
 }
 
@@ -2482,7 +2554,7 @@ gint file_data_verify_ci_list(GList *list, gchar **desc, gboolean with_sidecars)
                fd = work->data;
                work = work->next;
 
-               error = with_sidecars ? file_data_sc_verify_ci(fd) : file_data_verify_ci(fd);
+               error = with_sidecars ? file_data_sc_verify_ci(fd, list) : file_data_verify_ci(fd, list);
                all_errors |= error;
                common_errors &= error;