mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-26 12:12:10 +01:00
Merge branch 'master' into 'master'
gio: Expose g_file_query_info_for_copy() Closes gvfs#346 See merge request GNOME/glib!1449
This commit is contained in:
commit
3573a2d32d
@ -199,6 +199,7 @@ g_file_replace_contents
|
||||
g_file_replace_contents_async
|
||||
g_file_replace_contents_bytes_async
|
||||
g_file_replace_contents_finish
|
||||
g_file_build_attribute_list_for_copy
|
||||
g_file_copy_attributes
|
||||
g_file_create_readwrite
|
||||
g_file_create_readwrite_async
|
||||
|
113
gio/gfile.c
113
gio/gfile.c
@ -2695,14 +2695,36 @@ should_copy (GFileAttributeInfo *info,
|
||||
return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
build_attribute_list_for_copy (GFile *file,
|
||||
GFileCopyFlags flags,
|
||||
char **out_attributes,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
/**
|
||||
* g_file_build_attribute_list_for_copy:
|
||||
* @file: a #GFile to copy attributes to
|
||||
* @flags: a set of #GFileCopyFlags
|
||||
* @cancellable: (nullable): optional #GCancellable object,
|
||||
* %NULL to ignore
|
||||
* @error: a #GError, %NULL to ignore
|
||||
*
|
||||
* Prepares the file attribute query string for copying to @file.
|
||||
*
|
||||
* This function prepares an attribute query string to be
|
||||
* passed to g_file_query_info() to get a list of attributes
|
||||
* normally copied with the file (see g_file_copy_attributes()
|
||||
* for the detailed description). This function is used by the
|
||||
* implementation of g_file_copy_attributes() and is useful
|
||||
* when one needs to query and set the attributes in two
|
||||
* stages (e.g., for recursive move of a directory).
|
||||
*
|
||||
* Returns: an attribute query string for g_file_query_info(),
|
||||
* or %NULL if an error occurs.
|
||||
*
|
||||
* Since: 2.68
|
||||
*/
|
||||
char *
|
||||
g_file_build_attribute_list_for_copy (GFile *file,
|
||||
GFileCopyFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char *ret = NULL;
|
||||
GFileAttributeInfoList *attributes = NULL, *namespaces = NULL;
|
||||
GString *s = NULL;
|
||||
gboolean first;
|
||||
@ -2710,6 +2732,10 @@ build_attribute_list_for_copy (GFile *file,
|
||||
gboolean copy_all_attributes;
|
||||
gboolean skip_perms;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA;
|
||||
skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0;
|
||||
|
||||
@ -2763,8 +2789,7 @@ build_attribute_list_for_copy (GFile *file,
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
*out_attributes = g_string_free (s, FALSE);
|
||||
ret = g_string_free (s, FALSE);
|
||||
s = NULL;
|
||||
out:
|
||||
if (s)
|
||||
@ -2810,8 +2835,9 @@ g_file_copy_attributes (GFile *source,
|
||||
GFileInfo *info;
|
||||
gboolean source_nofollow_symlinks;
|
||||
|
||||
if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read,
|
||||
cancellable, error))
|
||||
attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags,
|
||||
cancellable, error);
|
||||
if (!attrs_to_read)
|
||||
return FALSE;
|
||||
|
||||
source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS;
|
||||
@ -3157,6 +3183,7 @@ file_copy_fallback (GFile *source,
|
||||
char *attrs_to_read;
|
||||
gboolean do_set_attributes = FALSE;
|
||||
GFileCreateFlags create_flags;
|
||||
GError *tmp_error = NULL;
|
||||
|
||||
/* need to know the file type */
|
||||
info = g_file_query_info (source,
|
||||
@ -3198,47 +3225,43 @@ file_copy_fallback (GFile *source,
|
||||
goto out;
|
||||
in = G_INPUT_STREAM (file_in);
|
||||
|
||||
if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read,
|
||||
cancellable, error))
|
||||
attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags,
|
||||
cancellable, error);
|
||||
if (!attrs_to_read)
|
||||
goto out;
|
||||
|
||||
if (attrs_to_read != NULL)
|
||||
/* Ok, ditch the previous lightweight info (on Unix we just
|
||||
* called lstat()); at this point we gather all the information
|
||||
* we need about the source from the opened file descriptor.
|
||||
*/
|
||||
g_object_unref (info);
|
||||
|
||||
info = g_file_input_stream_query_info (file_in, attrs_to_read,
|
||||
cancellable, &tmp_error);
|
||||
if (!info)
|
||||
{
|
||||
GError *tmp_error = NULL;
|
||||
|
||||
/* Ok, ditch the previous lightweight info (on Unix we just
|
||||
* called lstat()); at this point we gather all the information
|
||||
* we need about the source from the opened file descriptor.
|
||||
/* Not all gvfs backends implement query_info_on_read(), we
|
||||
* can just fall back to the pathname again.
|
||||
* https://bugzilla.gnome.org/706254
|
||||
*/
|
||||
g_object_unref (info);
|
||||
|
||||
info = g_file_input_stream_query_info (file_in, attrs_to_read,
|
||||
cancellable, &tmp_error);
|
||||
if (!info)
|
||||
if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
/* Not all gvfs backends implement query_info_on_read(), we
|
||||
* can just fall back to the pathname again.
|
||||
* https://bugzilla.gnome.org/706254
|
||||
*/
|
||||
if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
g_clear_error (&tmp_error);
|
||||
info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
cancellable, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (attrs_to_read);
|
||||
g_propagate_error (error, tmp_error);
|
||||
goto out;
|
||||
}
|
||||
g_clear_error (&tmp_error);
|
||||
info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
cancellable, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (attrs_to_read);
|
||||
g_propagate_error (error, tmp_error);
|
||||
goto out;
|
||||
}
|
||||
g_free (attrs_to_read);
|
||||
if (!info)
|
||||
goto out;
|
||||
|
||||
do_set_attributes = TRUE;
|
||||
}
|
||||
g_free (attrs_to_read);
|
||||
if (!info)
|
||||
goto out;
|
||||
|
||||
do_set_attributes = TRUE;
|
||||
|
||||
/* In the local file path, we pass down the source info which
|
||||
* includes things like unix::mode, to ensure that the target file
|
||||
|
@ -1094,6 +1094,12 @@ gboolean g_file_eject_mountable_with_operation_finish (GFile
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_68
|
||||
char * g_file_build_attribute_list_for_copy (GFile *file,
|
||||
GFileCopyFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_file_copy_attributes (GFile *source,
|
||||
GFile *destination,
|
||||
|
@ -1780,6 +1780,79 @@ test_writev_async_all_too_big_vectors (void)
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
static void
|
||||
test_build_attribute_list_for_copy (void)
|
||||
{
|
||||
GFile *tmpfile;
|
||||
GFileIOStream *iostream;
|
||||
GError *error = NULL;
|
||||
const GFileCopyFlags test_flags[] =
|
||||
{
|
||||
G_FILE_COPY_NONE,
|
||||
G_FILE_COPY_TARGET_DEFAULT_PERMS,
|
||||
G_FILE_COPY_ALL_METADATA,
|
||||
G_FILE_COPY_ALL_METADATA | G_FILE_COPY_TARGET_DEFAULT_PERMS,
|
||||
};
|
||||
gsize i;
|
||||
char *attrs;
|
||||
gchar *attrs_with_commas;
|
||||
|
||||
tmpfile = g_file_new_tmp ("tmp-build-attribute-list-for-copyXXXXXX",
|
||||
&iostream, &error);
|
||||
g_assert_no_error (error);
|
||||
g_io_stream_close ((GIOStream*)iostream, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_clear_object (&iostream);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_flags); i++)
|
||||
{
|
||||
GFileCopyFlags flags = test_flags[i];
|
||||
|
||||
attrs = g_file_build_attribute_list_for_copy (tmpfile, flags, NULL, &error);
|
||||
g_test_message ("Attributes for copy: %s", attrs);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (attrs);
|
||||
attrs_with_commas = g_strconcat (",", attrs, ",", NULL);
|
||||
g_free (attrs);
|
||||
|
||||
/* See g_local_file_class_init for reference. */
|
||||
if (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS)
|
||||
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_MODE ","));
|
||||
else
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_MODE ","));
|
||||
#ifdef G_OS_UNIX
|
||||
if (flags & G_FILE_COPY_ALL_METADATA)
|
||||
{
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_UID ","));
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_GID ","));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_UID ","));
|
||||
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_GID ","));
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_UTIMES
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ","));
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","));
|
||||
if (flags & G_FILE_COPY_ALL_METADATA)
|
||||
{
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ","));
|
||||
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC ","));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ","));
|
||||
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC ","));
|
||||
}
|
||||
#endif
|
||||
g_free (attrs_with_commas);
|
||||
}
|
||||
|
||||
(void) g_file_delete (tmpfile, NULL, NULL);
|
||||
g_clear_object (&tmpfile);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -1817,6 +1890,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/file/writev/async_all-no-vectors", test_writev_async_all_no_vectors);
|
||||
g_test_add_func ("/file/writev/async_all-to-big-vectors", test_writev_async_all_too_big_vectors);
|
||||
g_test_add_func ("/file/writev/async_all-cancellation", test_writev_async_all_cancellation);
|
||||
g_test_add_func ("/file/build-attribute-list-for-copy", test_build_attribute_list_for_copy);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user