app: do no overwite XCF when an error occurred at saving time.

We can cancel a file overwrite at the last second when closing the
stream by setting a cancelled cancellable. Current code was simply not
closing the stream, but this was not enough as overwriting was happening
anyway (probably when finalizing).
This will allow much safe saving process since we would not be
overwriting a previously sane XCF file when an error occurred (either in
our code or a memory error, or whatnot).
See also discussion in #2565.
This commit is contained in:
Jehan 2018-11-26 14:10:37 +01:00
parent d2f9549c9f
commit 076b53511a
1 changed files with 19 additions and 6 deletions

View File

@ -342,10 +342,11 @@ xcf_save_stream (Gimp *gimp,
GimpProgress *progress, GimpProgress *progress,
GError **error) GError **error)
{ {
XcfInfo info = { 0, }; XcfInfo info = { 0, };
const gchar *filename; const gchar *filename;
gboolean success = FALSE; gboolean success = FALSE;
GError *my_error = NULL; GError *my_error = NULL;
GCancellable *cancellable;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE); g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
@ -384,13 +385,25 @@ xcf_save_stream (Gimp *gimp,
success = xcf_save_image (&info, image, &my_error); success = xcf_save_image (&info, image, &my_error);
cancellable = g_cancellable_new ();
if (success) if (success)
{ {
if (progress) if (progress)
gimp_progress_set_text (progress, _("Closing '%s'"), filename); gimp_progress_set_text (progress, _("Closing '%s'"), filename);
success = g_output_stream_close (info.output, NULL, &my_error);
} }
else
{
/* When closing the stream, the image will be actually saved,
* unless we properly cancel it with a GCancellable.
* Not closing the stream is not an option either, as this will
* happen anyway when finalizing the output.
* So let's make sure now that we don't overwrite the XCF file
* when an error occurred.
*/
g_cancellable_cancel (cancellable);
}
success = g_output_stream_close (info.output, cancellable, &my_error);
g_object_unref (cancellable);
if (! success && my_error) if (! success && my_error)
g_propagate_prefixed_error (error, my_error, g_propagate_prefixed_error (error, my_error,