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)
This commit is contained in:
Alexander Larsson 2019-09-18 16:21:55 +02:00 committed by Alexander Larsson
parent 5db4631a79
commit 9bbe6fbb48
3 changed files with 74 additions and 11 deletions

View File

@ -6478,32 +6478,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;
}

View File

@ -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>

View File

@ -265,6 +265,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}"
@ -293,6 +295,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"