dentry源码:https://github.com/linuxdeepin/dde/tree/develop/lib/dentry
测试代码源码:https://github.com/linuxdeepin/dde/tree/desktop_test/app/desktop/test
// src ---> data->dest // we make use of 'goto' to minimize duplicated 'g_free*' statement gboolean traverse_directory (GFile* src, GFileProcessingFunc pre_hook, GFileProcessingFunc post_hook, gpointer data) { gboolean retval = TRUE; GError* error = NULL; GFileEnumerator* src_enumerator = NULL; src_enumerator = g_file_enumerate_children (src, "standard::*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); if (error != NULL) { //src_enumerator must be NULL, nothing to free. switch (error->code) { case G_IO_ERROR_NOT_FOUND: //TODO: showup a message box and quit. break; case G_IO_ERROR_NOT_DIRECTORY: //TODO:we're using a file. // if (pre_hook (src, data) == FALSE || post_hook (src, data) == FALSE) { g_error_free (error); return FALSE; } else { g_error_free (error); return TRUE; } default: g_debug("src found and is directory"); break; } g_warning ("traverse_directory 1: %s", error->message); g_error_free (error); return TRUE; } //here, we must be in a directory. //check if it's a symbolic link if (pre_hook (src, data) == FALSE) //src_enumerator must be freed { retval = FALSE; goto post_processing; } #if 1 char* src_uri = NULL; src_uri = g_file_get_uri (src); g_debug ("traverse_directory: chdir to : %s", src_uri); #endif GFileInfo* file_info = NULL; while ((file_info = g_file_enumerator_next_file (src_enumerator, NULL, &error)) != NULL) { //this should not be freed with g_free(). it'll be freed when we call g_object_unref //on file_info #if 1 const char* src_child_name = g_file_info_get_name (file_info); g_debug ("traverse_directory: %s", src_child_name); #endif TDData* tddata = NULL; GFile* src_child_file = NULL; GFile* dest_dir = NULL; //corresponding to src GFile* dest_child_file = NULL; //corresponding to src_child_file. tddata = new_td_data (); src_child_file = g_file_get_child (src, src_child_name); dest_dir = ((TDData*)data)->dest_file; if (dest_dir != NULL) { dest_child_file = g_file_get_child (dest_dir, src_child_name); #if 1 char* dest_child_file_uri = g_file_get_uri (dest_child_file); g_debug ("dest_child_file_uri: %s", dest_child_file_uri); g_free (dest_child_file_uri); #endif } tddata->dest_file = dest_child_file; tddata->cancellable = ((TDData*)data)->cancellable; //TODO: //get out the loop recursively when operation is cancelled. retval = traverse_directory (src_child_file, pre_hook, post_hook, tddata); g_object_unref (src_child_file); free_td_data (tddata); g_object_unref (file_info); file_info = NULL; if (retval == FALSE) goto post_processing; } //checking errors if (error != NULL) { g_warning ("traverse_directory 2: %s", error->message); g_error_free (error); } #if 1 //change to parent directory. g_debug ("traverse_directory: come out: %s", src_uri); g_free (src_uri); #endif post_processing: //close enumerator. g_file_enumerator_close (src_enumerator, NULL, &error); g_object_unref (src_enumerator); //checking errors if (error != NULL) { g_warning ("traverse_directory 3: %s", error->message); g_error_free (error); } //after processing child node. processing this directory. if (post_hook (src, data) == FALSE) return FALSE; return retval; }
if (g_file_is_native (src)) traverse_directory (src, _copy_files_async, _dummy_func, data); else _copy_files_async (src,data);
代码位置:dde/lib/dentry/fileops_copy.c -->fileops_copy()
此处判断如果是网络文件,那么traverse_directory
若是本地文件,直接_copy_files_async
此处需改进
记录:
不同遍历方式(由外而内,由内而外)
post_hook
pre_hook
/TODO:we're using a file. if (pre_hook (src, data) == FALSE || post_hook (src, data) == FALSE) { g_error_free (error); return FALSE; } else { g_error_free (error); return TRUE; } /// //here, we must be in a directory. //check if it's a symbolic link if (pre_hook (src, data) == FALSE) //src_enumerator must be freed { retval = FALSE; goto post_processing; }
2.不够完善,需要改进的traverse_directory中的g_warning----------已解决
fileops_moving时
** Message: fileops_move: Begin moving files ** Message: fileops_move: file 0: file:///home/ycl/dde/build/test_files/skype.desktop to dest: file:///home/ycl ** Message: GFileType=2 ** (desktop:25391): WARNING **: traverse_directory 1: 没有那个文件或目录 ** Message: fileops_move: End moving files
说明:
文件是存在的,但是还是报了警告
source:
g_warning ("traverse_directory 1: %s", error->message);
g_warning ("traverse_directory 2: %s", error->message);
g_warning ("traverse_directory 3: %s", error->message);
location:
traverse_directory()内
直接上改进后的code:
// src ---> data->dest // we make use of 'goto' to minimize duplicated 'g_free*' statement gboolean traverse_directory (GFile* src, GFileProcessingFunc pre_hook, GFileProcessingFunc post_hook, gpointer data) { gboolean retval = TRUE; GError* error = NULL; GFileEnumerator* src_enumerator = NULL; src_enumerator = g_file_enumerate_children (src, "standard::*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); if (error != NULL) { //src_enumerator must be NULL, nothing to free. switch (error->code) { case G_IO_ERROR_NOT_FOUND: //TODO: showup a message box and quit. g_debug("G_IO_ERROR_NOT_FOUND"); break; case G_IO_ERROR_NOT_DIRECTORY: //TODO:we're using a file. g_debug("G_IO_ERROR_NOT_DIRECTORY"); // if (pre_hook (src, data) == FALSE || post_hook (src, data) == FALSE) { g_error_free (error); return FALSE; } else { g_error_free (error); return TRUE; } default: g_debug("src found and is directory"); break; } // g_warning ("traverse_directory 1: %s", error->message); g_error_free (error); return TRUE; } //here, we must be in a directory. //check if it's a symbolic link if (pre_hook (src, data) == FALSE) //src_enumerator must be freed { retval = FALSE; goto post_processing; } #if 1 char* src_uri = NULL; src_uri = g_file_get_uri (src); g_debug ("traverse_directory: chdir to : %s", src_uri); #endif //begin g_file_enumerator_next_file ,we must check if the file type is symbolic_link then goto post_processing: GFileType type = g_file_query_file_type (src, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL); if (type == G_FILE_TYPE_SYMBOLIC_LINK) { //TODO: symbolic links g_debug ("-------src type is symbolic_link-------"); goto post_processing; } GFileInfo* file_info = NULL; while ((file_info = g_file_enumerator_next_file (src_enumerator, NULL, &error)) != NULL) { //this should not be freed with g_free(). it'll be freed when we call g_object_unref //on file_info #if 1 const char* src_child_name = g_file_info_get_name (file_info); g_debug ("traverse_directory: %s", src_child_name); #endif TDData* tddata = NULL; GFile* src_child_file = NULL; GFile* dest_dir = NULL; //corresponding to src GFile* dest_child_file = NULL; //corresponding to src_child_file. tddata = new_td_data (); src_child_file = g_file_get_child (src, src_child_name); dest_dir = ((TDData*)data)->dest_file; if (dest_dir != NULL) { dest_child_file = g_file_get_child (dest_dir, src_child_name); #if 1 char* dest_child_file_uri = g_file_get_uri (dest_child_file); g_debug ("dest_child_file_uri: %s", dest_child_file_uri); g_free (dest_child_file_uri); #endif } tddata->dest_file = dest_child_file; tddata->cancellable = ((TDData*)data)->cancellable; //TODO: //get out the loop recursively when operation is cancelled. retval = traverse_directory (src_child_file, pre_hook, post_hook, tddata); g_object_unref (src_child_file); free_td_data (tddata); g_object_unref (file_info); file_info = NULL; if (retval == FALSE) goto post_processing; } //checking errors if (error != NULL) { g_warning ("traverse_directory 2: %s", error->message); g_error_free (error); } #if 1 //change to parent directory. g_debug ("traverse_directory: come out: %s", src_uri); g_free (src_uri); #endif post_processing: //close enumerator. g_file_enumerator_close (src_enumerator, NULL, &error); g_object_unref (src_enumerator); //checking errors if (error != NULL) { g_warning ("traverse_directory 3: %s", error->message); g_error_free (error); } //after processing child node. processing this directory. if (post_hook (src, data) == FALSE) return FALSE; return retval; }
其实改动的地方很少,很简单。
注:
本来应该先判断error的各种情况,然后再switch case pre_hook post_hook, 同时分好类后,对不同类,进行不同error->message打印。
但是这样工作量大,且不现实。,同时也没必要。
因为我们一般只关心三种状态:
1. src是否存在
2.src是否是文件夹
甚至不需关心文件是不是单个文件,何种文件等等。
正好对应两种error->code:
G_IO_ERROR_NOT_FOUND
G_IO_ERROR_NOT_DIRECTORY
其实default中,就一定是DIRECTORY了。
至此,我们的目的本来就是打印信息,那么为何不直接在这三种情况下打印简单提示就可以解决这么繁杂的问题了。
故,不能为了考虑情况全面而去全面考虑。
3.应该对以下情况进行详细提示:--------未解决
case G_IO_ERROR_NOT_FOUND: //TODO: showup a message box and quit. g_debug("G_IO_ERROR_NOT_FOUND");