[gimp/gimp-2-10] Issue #4777: "New version available" after update.



commit bfc492fb1bba509a2c8aa3dd5911e5978d813618
Author: Jehan <jehan girinstud io>
Date:   Fri Oct 16 18:04:15 2020 +0200

    Issue #4777: "New version available" after update.
    
    The About dialog refreshes the release information relatively to
    currently running version before being displayed. No check of the remote
    JSON file is done, it only verifies whether any stored released
    version/revision is not same (or even lower) than the actually running
    version. Indeed existence of a stored release means that a newer version
    exists at check time only. On later run, this stored information may
    have become deprecated.
    
    (cherry picked from commit 5c89099f75bb329f8532156f3c63977b7b07dab1)

 app/dialogs/about-dialog.c |  19 ++--
 app/gimp-update.c          | 253 +++++++++++++++++++++++++++++++++++----------
 app/gimp-update.h          |   3 +-
 3 files changed, 211 insertions(+), 64 deletions(-)
---
diff --git a/app/dialogs/about-dialog.c b/app/dialogs/about-dialog.c
index bc1a4d3726..5db0fc4bb5 100644
--- a/app/dialogs/about-dialog.c
+++ b/app/dialogs/about-dialog.c
@@ -57,7 +57,8 @@ typedef struct
 {
   GtkWidget   *dialog;
 
-  GtkWidget   *update_frame;
+  GtkWidget      *update_frame;
+  GimpCoreConfig *config;
 
   GtkWidget   *anim_area;
   PangoLayout *layout;
@@ -120,6 +121,7 @@ about_dialog_create (GimpCoreConfig *config)
       gchar     *version;
 
       dialog.n_authors = G_N_ELEMENTS (authors) - 1;
+      dialog.config    = config;
 
       pixbuf = about_dialog_load_logo ();
 
@@ -203,6 +205,8 @@ static void
 about_dialog_map (GtkWidget       *widget,
                   GimpAboutDialog *dialog)
 {
+  gimp_update_refresh (dialog->config);
+
   if (dialog->layout && dialog->timer == 0)
     {
       dialog->state    = 0;
@@ -297,6 +301,12 @@ about_dialog_add_update (GimpAboutDialog *dialog,
   gchar     *date;
   gchar     *text;
 
+  if (dialog->update_frame)
+    {
+      gtk_widget_destroy (dialog->update_frame);
+      dialog->update_frame = NULL;
+    }
+
   /* Get the dialog vbox. */
   container = gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog));
   children = gtk_container_get_children (GTK_CONTAINER (container));
@@ -463,6 +473,7 @@ about_dialog_add_update (GimpAboutDialog *dialog,
   gtk_widget_show (frame);
 
   dialog->update_frame = frame;
+  g_object_add_weak_pointer (G_OBJECT (frame), (gpointer) &dialog->update_frame);
 
   /* Reconstruct the dialog when release info changes. */
   g_signal_connect (config, "notify::last-known-release",
@@ -849,12 +860,6 @@ about_dialog_last_release_changed (GimpCoreConfig   *config,
   if (! dialog->dialog)
     return;
 
-  if (dialog->update_frame)
-    {
-      gtk_widget_destroy (dialog->update_frame);
-      dialog->update_frame = NULL;
-    }
-
   about_dialog_add_update (dialog, config);
 }
 
diff --git a/app/gimp-update.c b/app/gimp-update.c
index 017051009b..cee1d53842 100644
--- a/app/gimp-update.c
+++ b/app/gimp-update.c
@@ -42,6 +42,130 @@
 #include "gimp-update.h"
 #include "gimp-version.h"
 
+static gboolean gimp_update_known           (GimpCoreConfig   *config,
+                                             const gchar      *last_version,
+                                             gint64            release_timestamp,
+                                             gint              build_revision,
+                                             const gchar      *comment);
+static gboolean gimp_version_break          (const gchar      *v,
+                                             gint             *major,
+                                             gint             *minor,
+                                             gint             *micro);
+static void     gimp_check_updates_callback (GObject          *source,
+                                             GAsyncResult     *result,
+                                             gpointer          user_data);
+static void     gimp_update_about_dialog    (GimpCoreConfig   *config,
+                                             const GParamSpec *pspec,
+                                             gpointer          user_data);
+
+/* Private Functions */
+
+/**
+ * gimp_update_known:
+ * @config:
+ * @last_version:
+ * @release_timestamp: must be non-zero is @last_version is not %NULL.
+ * @build_revision:
+ * @build_comment:
+ *
+ * Compare @last_version with currently running version. If the checked
+ * version is more recent than running version, then @config properties
+ * are updated appropriately (which may trigger a dialog depending on
+ * update policy settings).
+ * If @last_version is %NULL, the currently stored "last known release"
+ * is compared. Even if we haven't made any new remote checks, it is
+ * important to always compare again stored last release, otherwise we
+ * might warn of the same current version, or worse an older version.
+ *
+ * Returns: %TRUE is @last_version (or stored last known release if
+ * @last_version was %NULL) is newer than running version.
+ */
+static gboolean
+gimp_update_known (GimpCoreConfig *config,
+                   const gchar    *last_version,
+                   gint64          release_timestamp,
+                   gint            build_revision,
+                   const gchar    *build_comment)
+{
+  gboolean new_check = (last_version != NULL);
+  gint     major;
+  gint     minor;
+  gint     micro;
+
+  if (last_version && release_timestamp == 0)
+    {
+      /* I don't exit with a g_return_val_if_fail() assert because this
+       * is not necessarily a code bug. It may be data issues. So let's
+       * just return with an error printed on stderr.
+       */
+      g_printerr ("%s: version %s with no release dates.\n",
+                  G_STRFUNC, last_version);
+      return FALSE;
+    }
+
+  if (last_version == NULL)
+    {
+      last_version      = config->last_known_release;
+      release_timestamp = config->last_release_timestamp;
+      build_revision    = config->last_revision;
+      build_comment     = config->last_release_comment;
+    }
+
+  if (last_version)
+    {
+      if (gimp_version_break (last_version, &major, &minor, &micro))
+        {
+          if (/* We are using a newer version than last check. This could
+               * happen if updating the config files without having
+               * re-checked the remote JSON file.
+               */
+              (major < GIMP_MAJOR_VERSION ||
+               (major == GIMP_MAJOR_VERSION && minor < GIMP_MINOR_VERSION) ||
+               (major == GIMP_MAJOR_VERSION && minor == GIMP_MINOR_VERSION && micro < GIMP_MICRO_VERSION)) ||
+              /* Already using the last officially released
+               * revision. */
+              (major == GIMP_MAJOR_VERSION &&
+               minor == GIMP_MINOR_VERSION &&
+               micro == GIMP_MICRO_VERSION &&
+               build_revision <= gimp_version_get_revision ()))
+            {
+              last_version      = NULL;
+            }
+        }
+      else
+        {
+          /* If version is not properly parsed, something is wrong with
+           * upstream version number or parsing. This should not happen.
+           */
+          g_printerr ("%s: version not properly formatted: %s\n",
+                      G_STRFUNC, last_version);
+
+          return FALSE;
+        }
+    }
+
+  if (last_version == NULL)
+    {
+      release_timestamp = 0;
+      build_revision    = 0;
+      build_comment     = NULL;
+    }
+
+  if (new_check)
+    g_object_set (config,
+                  "check-update-timestamp", g_get_real_time() / G_USEC_PER_SEC,
+                  NULL);
+
+  g_object_set (config,
+                "last-release-timestamp", release_timestamp,
+                "last-known-release",     last_version,
+                "last-revision",          build_revision,
+                "last-release-comment",   build_comment,
+                NULL);
+
+  /* Are we running an old GIMP? */
+  return (last_version != NULL);
+}
 
 static gboolean
 gimp_version_break (const gchar *v,
@@ -92,17 +216,15 @@ gimp_check_updates_callback (GObject      *source,
                                    NULL, &error))
     {
       const gchar *platform;
-      const gchar *last_version   = NULL;
-      const gchar *release_date   = NULL;
+      const gchar *last_version      = NULL;
+      const gchar *release_date      = NULL;
+      const gchar *build_comment     = NULL;
+      gint64       release_timestamp = 0;
+      gint         build_revision    = 0;
       JsonParser  *parser;
       JsonPath    *path;
       JsonNode    *result;
       JsonArray   *versions;
-      JsonArray   *builds;
-      gint         build_revision = 0;
-      gint         major;
-      gint         minor;
-      gint         micro;
       gint         i;
 
       /* For Windows and macOS, let's look if installers are available.
@@ -117,8 +239,8 @@ gimp_check_updates_callback (GObject      *source,
       parser = json_parser_new ();
       if (! json_parser_load_from_data (parser, file_contents, file_length, &error))
         {
-          g_printerr("%s: parsing of %s failed: %s\n", G_STRFUNC,
-                     g_file_get_uri (G_FILE (source)), error->message);
+          g_printerr ("%s: parsing of %s failed: %s\n", G_STRFUNC,
+                      g_file_get_uri (G_FILE (source)), error->message);
           g_free (file_contents);
           g_clear_object (&parser);
           g_clear_error (&error);
@@ -157,80 +279,82 @@ gimp_check_updates_callback (GObject      *source,
 
           /* Note that we don't actually look for the highest version,
            * but for the highest version for which a build for your
-           * platform is available.
+           * platform (and optional build-id) is available.
+           *
+           * So we loop through the version list then the build array
+           * and break at first compatible release, since JSON arrays
+           * are ordered.
            */
           version = json_array_get_object_element (versions, i);
           if (json_object_has_member (version, platform))
             {
-              last_version = json_object_get_string_member (version, "version");
-              release_date = json_object_get_string_member (version, "date");
-              builds       = json_object_get_array_member (version, platform);
-              break;
-            }
-        }
+              JsonArray *builds;
+              gint       j;
 
-      /* If version is not properly parsed, something is wrong with
-       * upstream version number or parsing.  This should not happen.
-       */
-      if (gimp_version_break (last_version, &major, &minor, &micro))
-        {
-          const gchar *build_date    = NULL;
-          const gchar *build_comment = NULL;
-          GDateTime   *datetime;
-          gchar       *str;
-
-          if (major < GIMP_MAJOR_VERSION ||
-              (major == GIMP_MAJOR_VERSION && minor < GIMP_MINOR_VERSION) ||
-              (major == GIMP_MAJOR_VERSION && minor == GIMP_MINOR_VERSION && micro < GIMP_MICRO_VERSION))
-            {
-              /* We are using a newer version than last one (somehow). */
-              last_version = NULL;
-            }
-          else if (major == GIMP_MAJOR_VERSION &&
-                   minor == GIMP_MINOR_VERSION &&
-                   micro == GIMP_MICRO_VERSION)
-            {
-              for (i = 0; i < (gint) json_array_get_length (builds); i++)
+              builds = json_object_get_array_member (version, platform);
+
+              for (j = 0; j < (gint) json_array_get_length (builds); j++)
                 {
                   const gchar *build_id = NULL;
                   JsonObject  *build;
 
-                  build = json_array_get_object_element (builds, i);
+                  build = json_array_get_object_element (builds, j);
                   if (json_object_has_member (build, "build-id"))
                     build_id = json_object_get_string_member (build, "build-id");
                   if (g_strcmp0 (build_id, GIMP_BUILD_ID) == 0)
                     {
+                      /* Release date is the build date if any set,
+                       * otherwise the main version release date.
+                       */
+                      if (json_object_has_member (build, "date"))
+                        release_date = json_object_get_string_member (build, "date");
+                      else
+                        release_date = json_object_get_string_member (version, "date");
+
+                      /* These are optional data. */
                       if (json_object_has_member (build, "revision"))
                         build_revision = json_object_get_int_member (build, "revision");
-                      if (json_object_has_member (build, "date"))
-                        build_date = json_object_get_string_member (build, "date");
                       if (json_object_has_member (build, "comment"))
                         build_comment = json_object_get_string_member (build, "comment");
                       break;
                     }
                 }
-              if (build_revision <= gimp_version_get_revision ())
+
+              if (release_date)
                 {
-                  /* Already using the last officially released
-                   * revision. */
-                  last_version = NULL;
+                  last_version = json_object_get_string_member (version, "version");
+                  break;
                 }
             }
-          str = g_strdup_printf ("%s 00:00:00Z", build_date ? build_date : release_date);
+        }
+
+      if (last_version && release_date)
+        {
+          GDateTime *datetime;
+          gchar     *str;
+
+          str = g_strdup_printf ("%s 00:00:00Z", release_date);
           datetime = g_date_time_new_from_iso8601 (str, NULL);
           g_free (str);
+
           if (datetime)
             {
-              g_object_set (config,
-                            "check-update-timestamp", g_get_real_time() / G_USEC_PER_SEC,
-                            "last-release-timestamp", g_date_time_to_unix (datetime),
-                            "last-known-release",     last_version,
-                            "last-revision",          build_revision,
-                            "last-release-comment",   build_comment,
-                            NULL);
+              release_timestamp = g_date_time_to_unix (datetime);
               g_date_time_unref (datetime);
             }
+          else
+            {
+              /* JSON file data bug. */
+              g_printerr ("%s: release date for version %s not properly formatted: %s\n",
+                          G_STRFUNC, last_version, release_date);
+
+              last_version   = NULL;
+              release_date   = NULL;
+              build_revision = 0;
+              build_comment  = NULL;
+            }
         }
+      gimp_update_known (config, last_version, release_timestamp, build_revision, build_comment);
 
       g_object_unref (path);
       g_object_unref (parser);
@@ -265,11 +389,15 @@ gimp_update_about_dialog (GimpCoreConfig   *config,
     }
 }
 
+/* Public Functions */
+
 /*
  * gimp_update_auto_check:
  * @config:
  *
  * Run the check for newer versions of GIMP if conditions are right.
+ *
+ * Returns: %TRUE if a check was actually run.
  */
 gboolean
 gimp_update_auto_check (GimpCoreConfig *config)
@@ -302,7 +430,9 @@ gimp_update_auto_check (GimpCoreConfig *config)
                     (GCallback) gimp_update_about_dialog,
                     NULL);
 
-  return gimp_update_check (config);
+  gimp_update_check (config);
+
+  return TRUE;
 }
 
 /*
@@ -311,7 +441,7 @@ gimp_update_auto_check (GimpCoreConfig *config)
  *
  * Run the check for newer versions of GIMP inconditionnally.
  */
-gboolean
+void
 gimp_update_check (GimpCoreConfig *config)
 {
   GFile *gimp_versions;
@@ -326,6 +456,17 @@ gimp_update_check (GimpCoreConfig *config)
 #endif
   g_file_load_contents_async (gimp_versions, NULL, gimp_check_updates_callback, config);
   g_object_unref (gimp_versions);
+}
 
-  return TRUE;
+/*
+ * gimp_update_refresh:
+ * @config:
+ *
+ * Do not execute a remote check, but refresh the known release data as
+ * it may be outdated.
+ */
+void
+gimp_update_refresh (GimpCoreConfig *config)
+{
+  gimp_update_known (config, NULL, 0, 0, NULL);
 }
diff --git a/app/gimp-update.h b/app/gimp-update.h
index dcc665d94a..836f2bca57 100644
--- a/app/gimp-update.h
+++ b/app/gimp-update.h
@@ -23,7 +23,8 @@
 
 
 gboolean gimp_update_auto_check (GimpCoreConfig *config);
-gboolean gimp_update_check      (GimpCoreConfig *config);
+void     gimp_update_check      (GimpCoreConfig *config);
+void     gimp_update_refresh    (GimpCoreConfig *config);
 
 
 #endif /* __APP_GIMP_UPDATE_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]