[gnumeric] Save: verify that the target file hasn't changed underneath us.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Save: verify that the target file hasn't changed underneath us.
- Date: Sun, 25 Mar 2018 19:49:03 +0000 (UTC)
commit ff67fe99e377b63f2468aa1c8432c33714683a69
Author: Morten Welinder <terra gnome org>
Date: Sun Mar 25 15:48:21 2018 -0400
Save: verify that the target file hasn't changed underneath us.
NEWS | 1 +
configure.ac | 2 +-
src/gui-file.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++-
src/workbook-view.c | 54 +++++++++++++++++++++++++++++++++--
4 files changed, 130 insertions(+), 6 deletions(-)
---
diff --git a/NEWS b/NEWS
index b63cb6b..652938b 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Gnumeric 1.12.40
Morten:
* Add floating-point environment sanity check. [#794515]
+ * Before saving, verify that files hasn't changed on disk. [#334024]
--------------------------------------------------------------------------
Gnumeric 1.12.39
diff --git a/configure.ac b/configure.ac
index 4e3b9b8..b33afd6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -166,7 +166,7 @@ PKG_PROG_PKG_CONFIG(0.18)
dnl *****************************
libspreadsheet_reqs="
- libgoffice-${GOFFICE_API_VER} >= 0.10.38
+ libgoffice-${GOFFICE_API_VER} >= 0.10.40
libgsf-1 >= 1.14.33
libxml-2.0 >= 2.4.12
"
diff --git a/src/gui-file.c b/src/gui-file.c
index 78b7bc8..7c8d8fb 100644
--- a/src/gui-file.c
+++ b/src/gui-file.c
@@ -742,6 +742,61 @@ gui_file_save_as (WBCGtk *wbcg, WorkbookView *wb_view, GnmFileSaveAsStyle type,
return success;
}
+static gboolean
+warn_about_overwrite (WBCGtk *wbcg,
+ GDateTime *modtime,
+ GDateTime *known_modtime)
+{
+ GtkWidget *dialog;
+ int response;
+ char *shortname, *filename, *longname, *duri, *modtxt;
+ Workbook *wb = wb_control_get_workbook (GNM_WBC (wbcg));
+ const char *uri;
+ GDateTime *modtime_local;
+
+ uri = go_doc_get_uri (GO_DOC (wb));
+ filename = go_filename_from_uri (uri);
+ if (filename) {
+ shortname = g_filename_display_basename (filename);
+ } else {
+ shortname = g_filename_display_basename (uri);
+ }
+
+ duri = g_uri_unescape_string (uri, NULL);
+ longname = duri
+ ? g_filename_display_name (duri)
+ : g_strdup (uri);
+
+ modtime_local = g_date_time_to_local (modtime);
+ modtxt = g_date_time_format (modtime_local, _("%F %T"));
+ g_date_time_unref (modtime_local);
+
+ dialog = gtk_message_dialog_new_with_markup
+ (wbcg_toplevel (wbcg),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("The file you are about to save has changed on disk. If you continue, you will overwrite
someone else's changes.\n\n"
+ "File: <b>%s</b>\n"
+ "Location: %s\n\n"
+ "Last modified: <b>%s</b>\n"),
+ shortname, longname, modtxt);
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("Overwrite"), GTK_RESPONSE_YES,
+ _("Cancel"), GTK_RESPONSE_NO,
+ NULL);
+ g_free (shortname);
+ g_free (longname);
+ g_free (duri);
+ g_free (filename);
+ g_free (modtxt);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
+ response = go_gtk_dialog_run (GTK_DIALOG (dialog),
+ wbcg_toplevel (wbcg));
+ return response == GTK_RESPONSE_YES;
+}
+
gboolean
gui_file_save (WBCGtk *wbcg, WorkbookView *wb_view)
{
@@ -760,17 +815,37 @@ gui_file_save (WBCGtk *wbcg, WorkbookView *wb_view)
return gui_file_save_as (wbcg, wb_view,
GNM_FILE_SAVE_AS_STYLE_SAVE, NULL);
else {
- gboolean ok;
+ gboolean ok = TRUE;
+ const char *uri = go_doc_get_uri (GO_DOC (wb));
+ GDateTime *known_modtime = go_doc_get_modtime (GO_DOC (wb));
+ GDateTime *modtime = go_file_get_modtime (uri);
+ gboolean debug_modtime = gnm_debug_flag ("modtime");
/* We need a ref because a Ctrl-Q at the wrong time will
cause the workbook to disappear at the end of the
save. */
g_object_ref (wb);
- ok = wb_view_save (wb_view, GO_CMD_CONTEXT (wbcg));
+ if (modtime && known_modtime) {
+ if (g_date_time_equal (known_modtime, modtime)) {
+ if (debug_modtime)
+ g_printerr ("Modtime match\n");
+ } else {
+ if (debug_modtime)
+ g_printerr ("Modtime mismatch\n");
+ ok = warn_about_overwrite (wbcg, modtime, known_modtime);
+ }
+ }
+
+ if (ok)
+ ok = wb_view_save (wb_view, GO_CMD_CONTEXT (wbcg));
if (ok)
workbook_update_history (wb, GNM_FILE_SAVE_AS_STYLE_SAVE);
g_object_unref (wb);
+
+ if (modtime)
+ g_date_time_unref (modtime);
+
return ok;
}
}
diff --git a/src/workbook-view.c b/src/workbook-view.c
index 37838ab..0a71175 100644
--- a/src/workbook-view.c
+++ b/src/workbook-view.c
@@ -1095,6 +1095,31 @@ wb_view_save_to_uri (WorkbookView *wbv, GOFileSaver const *fs,
}
}
+static GDateTime *
+get_uri_modtime (GsfInput *input, const char *uri)
+{
+ GDateTime *modtime = NULL;
+
+ if (input) {
+ modtime = gsf_input_get_modtime (input);
+ if (modtime)
+ g_date_time_ref (modtime);
+ }
+
+ if (!modtime)
+ modtime = go_file_get_modtime (uri);
+
+ if (gnm_debug_flag ("modtime")) {
+ char *s = modtime
+ ? g_date_time_format (modtime, "%F %T")
+ : g_strdup ("?");
+ g_printerr ("Modtime of %s is %s\n", uri, s);
+ g_free (s);
+ }
+
+ return modtime;
+}
+
/**
* wb_view_save_as:
* @wbv: Workbook View
@@ -1132,12 +1157,20 @@ wb_view_save_as (WorkbookView *wbv, GOFileSaver *fs, char const *uri,
has_error = go_io_error_occurred (io_context);
has_warning = go_io_warning_occurred (io_context);
if (!has_error) {
- if (workbook_set_saveinfo
- (wb, go_file_saver_get_format_level (fs), fs)) {
+ GOFileFormatLevel fl = go_file_saver_get_format_level (fs);
+ if (workbook_set_saveinfo (wb, fl, fs)) {
if (go_doc_set_uri (GO_DOC (wb), uri)) {
+ GDateTime *modtime;
+
go_doc_set_dirty (GO_DOC (wb), FALSE);
/* See 634792. */
go_doc_set_pristine (GO_DOC (wb), FALSE);
+
+ modtime = get_uri_modtime (NULL, uri);
+ go_doc_set_modtime (GO_DOC (wb), modtime);
+ if (gnm_debug_flag ("modtime"))
+ g_printerr ("Modtime set\n");
+ g_date_time_unref (modtime);
}
} else
workbook_set_last_export_uri (wb, uri);
@@ -1168,12 +1201,14 @@ wb_view_save (WorkbookView *wbv, GOCmdContext *context)
Workbook *wb;
GOFileSaver *fs;
gboolean has_error, has_warning;
+ char const *uri;
g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
g_return_val_if_fail (GO_IS_CMD_CONTEXT (context), FALSE);
wb = wb_view_get_workbook (wbv);
g_object_ref (wb);
+ uri = go_doc_get_uri (GO_DOC (wb));
fs = workbook_get_file_saver (wb);
if (fs == NULL)
@@ -1190,8 +1225,14 @@ wb_view_save (WorkbookView *wbv, GOCmdContext *context)
has_error = go_io_error_occurred (io_context);
has_warning = go_io_warning_occurred (io_context);
- if (!has_error)
+ if (!has_error) {
+ GDateTime *modtime = get_uri_modtime (NULL, uri);
+ go_doc_set_modtime (GO_DOC (wb), modtime);
+ if (gnm_debug_flag ("modtime"))
+ g_printerr ("Modtime set\n");
+ g_date_time_unref (modtime);
go_doc_set_dirty (GO_DOC (wb), FALSE);
+ }
if (has_error || has_warning)
go_io_error_display (io_context);
@@ -1267,12 +1308,19 @@ workbook_view_new_from_input (GsfInput *input,
if (optional_fmt != NULL) {
Workbook *new_wb;
gboolean old;
+ GDateTime *modtime;
new_wbv = workbook_view_new (NULL);
new_wb = wb_view_get_workbook (new_wbv);
if (optional_uri)
go_doc_set_uri (GO_DOC (new_wb), optional_uri);
+ // Grab the modtime before we actually do the reading
+ modtime = get_uri_modtime (input, optional_uri);
+ go_doc_set_modtime (GO_DOC (new_wb), modtime);
+ if (modtime)
+ g_date_time_unref (modtime);
+
/* disable recursive dirtying while loading */
old = workbook_enable_recursive_dirty (new_wb, FALSE);
go_file_opener_open (optional_fmt, optional_enc, io_context,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]