Add a hidden preference 'use_safe_file_saving' to save files to disk by creating a temporary file first. This has serious side effects, please read the documentation before enabling this.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@3722 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
parent
fae6486182
commit
8fcef38e82
@ -9,6 +9,11 @@
|
||||
document_get_basename_for_display() to the plugin API.
|
||||
* doc/geany.html, doc/geany.txt, src/toolbar.c:
|
||||
Add new toolbar element: Print (patch by Roland Baudin, thanks).
|
||||
* doc/geany.html, doc/geany.txt, src/document.c, src/document.h,
|
||||
src/keyfile.c:
|
||||
Add a hidden preference 'use_safe_file_saving' to save files to disk
|
||||
by creating a temporary file first. This has serious side effects,
|
||||
please read the documentation before enabling this.
|
||||
|
||||
|
||||
2009-04-20 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
@ -4221,6 +4221,30 @@ if you have VTE termcap files other than
|
||||
<tt class="docutils literal"><span class="pre">vte/termcap/xterm</span></tt>.</td>
|
||||
<td>xterm</td>
|
||||
</tr>
|
||||
<tr><td><strong>File related</strong></td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>use_safe_file_saving</td>
|
||||
<td>Defines the mode how Geany saves files to
|
||||
disk. If disabled, Geany directly writes
|
||||
the content of the document to disk. This
|
||||
might cause in loss of data when there is
|
||||
no more free space on disk to save the
|
||||
file. When set to true, Geany first saves
|
||||
the contents into a temporary file and if
|
||||
this succeeded, the temporary file is
|
||||
moved to the real file to save.
|
||||
This gives better error checking in case of
|
||||
no more free disk space. But it also
|
||||
destroys hard links of the original file
|
||||
and its permissions (e.g. executable flags
|
||||
are reset). Use this with care as it can
|
||||
break things seriously.
|
||||
The better approach would be to ensure your
|
||||
disk won't run out of free space.</td>
|
||||
<td>false</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -4792,7 +4816,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE.</p>
|
||||
<div class="footer">
|
||||
<hr class="footer" />
|
||||
<a class="reference external" href="geany.txt">View document source</a>.
|
||||
Generated on: 2009-04-21 19:06 UTC.
|
||||
Generated on: 2009-04-21 19:30 UTC.
|
||||
Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
|
||||
|
||||
</div>
|
||||
|
@ -3704,6 +3704,24 @@ allow_always_save Whether files can be saved always, even if f
|
||||
emulation Terminal emulation mode. Only change this xterm
|
||||
if you have VTE termcap files other than
|
||||
``vte/termcap/xterm``.
|
||||
**File related**
|
||||
use_safe_file_saving Defines the mode how Geany saves files to false
|
||||
disk. If disabled, Geany directly writes
|
||||
the content of the document to disk. This
|
||||
might cause in loss of data when there is
|
||||
no more free space on disk to save the
|
||||
file. When set to true, Geany first saves
|
||||
the contents into a temporary file and if
|
||||
this succeeded, the temporary file is
|
||||
moved to the real file to save.
|
||||
This gives better error checking in case of
|
||||
no more free disk space. But it also
|
||||
destroys hard links of the original file
|
||||
and its permissions (e.g. executable flags
|
||||
are reset). Use this with care as it can
|
||||
break things seriously.
|
||||
The better approach would be to ensure your
|
||||
disk won't run out of free space.
|
||||
================================ =========================================== ==================
|
||||
|
||||
|
||||
|
@ -1680,34 +1680,55 @@ _("An error occurred while converting the file from UTF-8 in \"%s\". The file re
|
||||
}
|
||||
|
||||
|
||||
static gint write_data_to_disk(GeanyDocument *doc, const gchar *locale_filename,
|
||||
const gchar *data, gint len)
|
||||
static gchar *write_data_to_disk(GeanyDocument *doc, const gchar *locale_filename,
|
||||
const gchar *data, gint len)
|
||||
{
|
||||
FILE *fp;
|
||||
gint bytes_written;
|
||||
gint err = 0;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail(data != NULL, EINVAL);
|
||||
g_return_val_if_fail(doc != NULL, g_strdup(g_strerror(EINVAL)));
|
||||
g_return_val_if_fail(data != NULL, g_strdup(g_strerror(EINVAL)));
|
||||
|
||||
fp = g_fopen(locale_filename, "wb");
|
||||
if (G_UNLIKELY(fp == NULL))
|
||||
return errno;
|
||||
/* we never use g_file_set_contents() for remote files as Geany only writes such files
|
||||
* 'into' the Fuse mountpoint, the file itself is then written by GVfs on the target
|
||||
* remote filesystem. */
|
||||
if (! file_prefs.use_safe_file_saving || doc->priv->is_remote)
|
||||
{
|
||||
fp = g_fopen(locale_filename, "wb");
|
||||
if (G_UNLIKELY(fp == NULL))
|
||||
return g_strdup(g_strerror(errno));
|
||||
|
||||
bytes_written = fwrite(data, sizeof(gchar), len, fp);
|
||||
bytes_written = fwrite(data, sizeof(gchar), len, fp);
|
||||
|
||||
if (G_UNLIKELY(len != bytes_written))
|
||||
err = errno;
|
||||
if (G_UNLIKELY(len != bytes_written))
|
||||
err = errno;
|
||||
|
||||
fclose(fp);
|
||||
fclose(fp);
|
||||
|
||||
if (err != 0)
|
||||
return g_strdup(g_strerror(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_file_set_contents(locale_filename, data, len, &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
gchar *msg = g_strdup(error->message);
|
||||
g_error_free(error);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
/* now the file is on disk, set real_path */
|
||||
if (err == 0 && doc->real_path == NULL)
|
||||
if (doc->real_path == NULL)
|
||||
{
|
||||
doc->real_path = tm_get_real_path(locale_filename);
|
||||
doc->priv->is_remote = utils_is_remote_path(locale_filename);
|
||||
}
|
||||
|
||||
return err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -1726,9 +1747,9 @@ static gint write_data_to_disk(GeanyDocument *doc, const gchar *locale_filename,
|
||||
**/
|
||||
gboolean document_save_file(GeanyDocument *doc, gboolean force)
|
||||
{
|
||||
gchar *errmsg;
|
||||
gchar *data;
|
||||
gsize len;
|
||||
gint err;
|
||||
gchar *locale_filename;
|
||||
|
||||
g_return_val_if_fail(doc != NULL, FALSE);
|
||||
@ -1793,17 +1814,17 @@ gboolean document_save_file(GeanyDocument *doc, gboolean force)
|
||||
doc->priv->file_disk_status = FILE_IGNORE;
|
||||
|
||||
/* actually write the content of data to the file on disk */
|
||||
err = write_data_to_disk(doc, locale_filename, data, len);
|
||||
errmsg = write_data_to_disk(doc, locale_filename, data, len);
|
||||
g_free(data);
|
||||
|
||||
if (G_UNLIKELY(err != 0))
|
||||
if (errmsg != NULL)
|
||||
{
|
||||
ui_set_statusbar(TRUE, _("Error saving file (%s)."), g_strerror(err));
|
||||
dialogs_show_msgbox_with_secondary(GTK_MESSAGE_ERROR,
|
||||
_("Error saving file."), g_strerror(err));
|
||||
ui_set_statusbar(TRUE, _("Error saving file (%s)."), errmsg);
|
||||
dialogs_show_msgbox_with_secondary(GTK_MESSAGE_ERROR, _("Error saving file."), errmsg);
|
||||
doc->priv->file_disk_status = FILE_OK;
|
||||
utils_beep();
|
||||
g_free(locale_filename);
|
||||
g_free(errmsg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ typedef struct GeanyFilePrefs
|
||||
gint default_eol_character;
|
||||
gint disk_check_timeout;
|
||||
gboolean cmdline_new_files; /* New file if command-line filename doesn't exist */
|
||||
gboolean use_safe_file_saving;
|
||||
}
|
||||
GeanyFilePrefs;
|
||||
|
||||
|
@ -172,6 +172,8 @@ static void init_pref_groups(void)
|
||||
"show_symbol_list_expanders", TRUE);
|
||||
stash_group_add_boolean(group, &ui_prefs.allow_always_save,
|
||||
"allow_always_save", FALSE);
|
||||
stash_group_add_boolean(group, &file_prefs.use_safe_file_saving,
|
||||
"use_safe_file_saving", FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user