From 2d4d1e54d6943cdd7a818324110789a59622f2a0 Mon Sep 17 00:00:00 2001 From: Alexander Schwinn <alexxcons@xfce.org> Date: Thu, 9 Feb 2023 22:49:56 +0100 Subject: [PATCH] Support undo trash for linked pathes (#1030) --- thunar/thunar-gio-extensions.c | 41 ++++++++++++++++++++++++++++++++++ thunar/thunar-gio-extensions.h | 3 ++- thunar/thunar-job-operation.c | 27 ++++++++++++++++++++-- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/thunar/thunar-gio-extensions.c b/thunar/thunar-gio-extensions.c index b24368022..64431baf7 100644 --- a/thunar/thunar-gio-extensions.c +++ b/thunar/thunar-gio-extensions.c @@ -29,6 +29,10 @@ #include <gio/gdesktopappinfo.h> #endif +#ifndef HAVE_REALPATH +#define realpath(path, resolved_path) NULL +#endif + #include <libxfce4util/libxfce4util.h> #include <thunar/thunar-file.h> @@ -1418,4 +1422,41 @@ thunar_g_file_get_link_path_for_symlink (GFile *file_to_link, link_path = g_strconcat ("/", relative_path, NULL); g_free (relative_path); return link_path; +} + + + +/** + * thunar_g_file_get_resolved_path: + * @file : #GFile for which the path will be resolved + * + * Gets the local pathname with resolved symlinks for GFile, if one exists. + * If non-NULL, this is guaranteed to be an absolute, canonical path. + * + * This only will work if all components of the #GFile path actually do exist + * + * Return value: (nullable) (transfer full): A #gchar on success and %NULL on failure. + * The returned string should be freed with g_free() when no longer needed. + **/ +char* +thunar_g_file_get_resolved_path (GFile *file) +{ + gchar *path; + gchar *real_path; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + + path = g_file_get_path (file); + + /* No local path for file found */ + if (path == NULL) + return NULL; + + real_path = realpath (path, NULL); + + if (real_path == NULL) + g_warning ("Failed to resolve path: '%s' Error: %s\n", path, strerror (errno)); + + g_free (path); + return real_path; } \ No newline at end of file diff --git a/thunar/thunar-gio-extensions.h b/thunar/thunar-gio-extensions.h index 07433a234..03715ae41 100644 --- a/thunar/thunar-gio-extensions.h +++ b/thunar/thunar-gio-extensions.h @@ -121,8 +121,9 @@ gboolean thunar_g_file_set_executable_flags (GFile *file, GError **error); gboolean thunar_g_file_is_in_xdg_data_dir (GFile *file); gboolean thunar_g_file_is_desktop_file (GFile *file); -char * thunar_g_file_get_link_path_for_symlink (GFile *file_to_link, +char *thunar_g_file_get_link_path_for_symlink (GFile *file_to_link, GFile *symlink); +char *thunar_g_file_get_resolved_path (GFile *file); G_END_DECLS #endif /* !__THUNAR_GIO_EXTENSIONS_H__ */ diff --git a/thunar/thunar-job-operation.c b/thunar/thunar-job-operation.c index e2ef4495c..6861bd169 100644 --- a/thunar/thunar-job-operation.c +++ b/thunar/thunar-job-operation.c @@ -663,12 +663,35 @@ thunar_job_operation_restore_from_trash (ThunarJobOperation *operation, } /* set up a hash table for the files we deleted */ - files_trashed = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, NULL, NULL); + files_trashed = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL); /* add all the files that were deleted in the hash table so we can check if a file * was deleted as a part of this operation or not in constant time. */ for (GList *lp = operation->target_file_list; lp != NULL; lp = lp->next) - g_hash_table_add (files_trashed, lp->data); + { + GFile *parent = g_file_get_parent (lp->data); + gchar *real_path = NULL; + + /* Try to resolve symlinks, otherwise Gfiles wont match */ + /* (All files located in trash have symlinks resolved) */ + if (parent != NULL) + { + gchar *real_path_parent = NULL; + gchar *basename = g_file_get_basename (lp->data); + real_path_parent = thunar_g_file_get_resolved_path (parent); + g_object_unref (parent); + if (real_path_parent != NULL && basename != NULL) + real_path = g_build_filename (real_path_parent, basename, NULL); + g_free (basename); + g_free (real_path_parent); + } + + if (real_path != NULL) + g_hash_table_add (files_trashed, g_file_new_for_path (real_path)); + else + g_hash_table_add (files_trashed, g_object_ref (lp->data)); + g_free (real_path); + } /* iterate over the files in the trash, adding them to source and target lists of * the files which are to be restored and their original paths */ -- GitLab