DDE后端之dentry(四):traverse_directory

dentry源码:https://github.com/linuxdeepin/dde/tree/develop/lib/dentry

测试代码源码:https://github.com/linuxdeepin/dde/tree/desktop_test/app/desktop/test


初始源码:(有很多Bug)
// 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;
}

 



先说travese_directory的缺陷:
1.nautilus网络文件的拖动问题,或者整个文件夹的复制。不能复制文件夹内部文件的原因:api不支持对网络文件夹内部文件遍历。---未解决
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");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值