File 0015-Support-multiple-versions-in-required-flatpak-metadata-key.patch of Package flatpak.14328

From e66c9ed56c4205380c232e1319a7d848c9b4e925 Mon Sep 17 00:00:00 2001
From: Alexander Larsson <alexl@redhat.com>
Date: Wed, 18 Sep 2019 16:21:55 +0200
Subject: [PATCH] Support multiple versions in required-flatpak metadata key

Support a list of versions that are supported. This will be useful
for e.g. the extra_data for extensions once that is backported to
1.2, because that will require it to say that it is supported for
> 1.2.5 in the 1.2 series and > 1.4.2 otherwise.

Closes: #3112
Approved by: alexlarsson

(cherry picked from commit 5026f01153c21a2906f7c7b7b573543691daccfd)
(cherry picked from commit 9bbe6fbb480f32c808bdc46c7937eb5fce804ac4)

Closes: #3115
Approved by: alexlarsson
---
 common/flatpak-utils.c   | 67 ++++++++++++++++++++++++++++++++++------
 doc/flatpak-metadata.xml |  9 +++++-
 tests/test-repo.sh       |  9 ++++++
 3 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
index a2740db1d..4af758604 100644
--- a/common/flatpak-utils.c
+++ b/common/flatpak-utils.c
@@ -5917,32 +5917,79 @@ flatpak_check_required_version (const char *ref,
                                 GKeyFile   *metakey,
                                 GError    **error)
 {
-  g_autofree char *required_version = NULL;
+  g_auto(GStrv) required_versions = NULL;
   const char *group;
-  int required_major, required_minor, required_micro;
+  int max_required_major = 0, max_required_minor = 0;
+  const char *max_required_version = "0.0";
+  int i;
 
   if (g_str_has_prefix (ref, "app/"))
     group = "Application";
   else
     group = "Runtime";
 
-  required_version = g_key_file_get_string (metakey, group, "required-flatpak", NULL);
-  if (required_version)
+  /* We handle handle multiple version requirements here. Each requirement must
+   * be in the form major.minor.micro, and if the flatpak version matches the
+   * major.minor part, t must be equal or later in the micro. If the major.minor part
+   * doesn't exactly match any of the specified requirements it must be larger
+   * than the maximum specified requirement.
+   *
+   * For example, specifying
+   *   required-flatpak=1.6.2;1.4.2;1.0.2;
+   * would allow flatpak versions:
+   *  1.7.0, 1.6.2, 1.6.3, 1.4.2, 1.4.3, 1.0.2, 1.0.3
+   * but not:
+   *  1.6.1, 1.4.1 or 1.2.100.
+   *
+   * The goal here is to be able to specify a version (like 1.6.2 above) where a feature
+   * was introduced, but also allow backports of said feature to earlier version series.
+   *
+   * Earlier versions that only support specifying one version will only look at the first
+   * element in the list, so put the largest version first.
+   */
+  required_versions = g_key_file_get_string_list (metakey, group, "required-flatpak", NULL, NULL);
+  if (required_versions == 0 || required_versions[0] == NULL)
+    return TRUE;
+
+  for (i = 0; required_versions[i] != NULL; i++)
     {
+      int required_major, required_minor, required_micro;
+      const char *required_version = required_versions[i];
+
       if (sscanf (required_version, "%d.%d.%d", &required_major, &required_minor, &required_micro) != 3)
         return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA,
                                    _("Invalid require-flatpak argument %s"), required_version);
       else
         {
-          if (required_major > PACKAGE_MAJOR_VERSION ||
-              (required_major == PACKAGE_MAJOR_VERSION && required_minor > PACKAGE_MINOR_VERSION) ||
-              (required_major == PACKAGE_MAJOR_VERSION && required_minor == PACKAGE_MINOR_VERSION && required_micro > PACKAGE_MICRO_VERSION))
-            return flatpak_fail_error (error, FLATPAK_ERROR_NEED_NEW_FLATPAK,
-                                       _("%s needs a later flatpak version (%s)"),
-                                       ref, required_version);
+          /* If flatpak is in the same major.minor series as the requirement, do a micro check */
+          if (required_major == PACKAGE_MAJOR_VERSION && required_minor == PACKAGE_MINOR_VERSION)
+            {
+              if (required_micro <= PACKAGE_MICRO_VERSION)
+                return TRUE;
+              else
+                return flatpak_fail_error (error, FLATPAK_ERROR_NEED_NEW_FLATPAK,
+                                           _("%s needs a later flatpak version (%s)"),
+                                           ref, required_version);
+            }
+
+          /* Otherwise, keep track of the largest major.minor that is required */
+          if ((required_major > max_required_major) ||
+              (required_major == max_required_major &&
+               required_minor > max_required_minor))
+            {
+              max_required_major = required_major;
+              max_required_minor = required_minor;
+              max_required_version = required_version;
+            }
         }
     }
 
+  if (max_required_major > PACKAGE_MAJOR_VERSION ||
+      (max_required_major == PACKAGE_MAJOR_VERSION && max_required_minor > PACKAGE_MINOR_VERSION))
+    return flatpak_fail_error (error, FLATPAK_ERROR_NEED_NEW_FLATPAK,
+                               _("%s needs a later flatpak version (%s)"),
+                               ref, max_required_version);
+
   return TRUE;
 }
 
diff --git a/doc/flatpak-metadata.xml b/doc/flatpak-metadata.xml
index 62db51346..e3e60bf45 100644
--- a/doc/flatpak-metadata.xml
+++ b/doc/flatpak-metadata.xml
@@ -100,12 +100,19 @@
                     </listitem>
                 </varlistentry>
                 <varlistentry>
-                    <term><option>required-flatpak</option> (string)</term>
+                    <term><option>required-flatpak</option> (string list)</term>
                     <listitem><para>
                         The required version of Flatpak to run this application
                         or runtime. For applications, this was available since
                         0.8.0. For runtimes, this was available since 0.9.1,
                         and backported to 0.8.3 for the 0.8.x branch.
+                      </para><para>
+                        Flatpak after version 1.4.3 and 1.2.5 support multiple versions here.
+                        This can be useful if you need to support features that are backported
+                        to a previous stable series. For example if you want to use a feature
+                        added in 1.6.0 that was also backported to 1.4.4 you would use
+                        <literal>1.6.0;1.4.4;</literal>. Note that older versions of flatpak will
+                        just use the first element in the list, so make that the largest version.
                     </para></listitem>
                 </varlistentry>
                 <varlistentry>
diff --git a/tests/test-repo.sh b/tests/test-repo.sh
index ee77b8c8b..dca0a0d5d 100755
--- a/tests/test-repo.sh
+++ b/tests/test-repo.sh
@@ -256,6 +256,8 @@ make_required_version_app org.test.NeedNewerMaster "$(expr ${V[0]} + 1).${V[1]}.
 make_required_version_app org.test.NeedOlderMinor "${V[0]}.$(expr ${V[1]} - 1).${V[2]}"
 make_required_version_app org.test.MultiVersionFallback "${V[0]}.${V[1]}.${V[2]};1.0.0;"
 make_required_version_app org.test.MultiVersionFallbackFail "${V[0]}.$(expr ${V[1]} + 1).${V[2]};1.0.0;"
+make_required_version_app org.test.MultiVersionOk "${V[0]}.$(expr ${V[1]} + 1).0;${V[0]}.${V[1]}.${V[2]};"
+make_required_version_app org.test.MultiVersionNotOk "${V[0]}.$(expr ${V[1]} + 1).0;${V[0]}.${V[1]}.$(expr ${V[2]} + 1);"
 
 update_repo $REPONAME "${COLLECTION_ID}"
 
@@ -284,6 +286,13 @@ if ${FLATPAK} ${U} install -y test-repo org.test.MultiVersionFallbackFail 2> ins
 fi
 assert_file_has_content install-error-log "needs a later flatpak version"
 
+${FLATPAK} ${U} install -y test-repo org.test.MultiVersionOk
+
+if ${FLATPAK} ${U} install -y test-repo org.test.MultiVersionNotOk 2> install-error-log; then
+    assert_not_reached "Should not be able to install with wrong multi version"
+fi
+assert_file_has_content install-error-log "needs a later flatpak version"
+
 ${FLATPAK} ${U} uninstall -y --all
 
 echo "ok handles version requirements"
openSUSE Build Service is sponsored by