mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 06:23:38 +00:00
compatibility: Implement a version comparator.
This commit is contained in:
@@ -1,5 +1,43 @@
|
|||||||
|
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
|
from zerver.views.compatibility import version_lt
|
||||||
|
|
||||||
|
class VersionTest(ZulipTestCase):
|
||||||
|
data = [case.split() for case in '''
|
||||||
|
1.2.3 < 1.2.4
|
||||||
|
1.2.3 = 1.2.3
|
||||||
|
1.4.1 > 1.2.3
|
||||||
|
1.002a = 1.2a
|
||||||
|
1.2.3 ? 1.2-dev
|
||||||
|
1.2-dev ? 1.2a
|
||||||
|
1.2a ? 1.2rc3
|
||||||
|
1.2rc3 ? 1.2
|
||||||
|
1.2 ? 1.2-g0f1e2d3c4
|
||||||
|
10.1 > 1.2
|
||||||
|
0.17.18 < 16.2.96
|
||||||
|
9.10.11 < 16.2.96
|
||||||
|
15.1.95 < 16.2.96
|
||||||
|
16.2.96 = 16.2.96
|
||||||
|
20.0.103 > 16.2.96
|
||||||
|
'''.strip().split('\n')]
|
||||||
|
|
||||||
|
def test_version_lt(self) -> None:
|
||||||
|
for ver1, cmp, ver2 in self.data:
|
||||||
|
msg = 'expected {} {} {}'.format(ver1, cmp, ver2)
|
||||||
|
if cmp == '<':
|
||||||
|
self.assertTrue(version_lt(ver1, ver2), msg=msg)
|
||||||
|
self.assertFalse(version_lt(ver2, ver1), msg=msg)
|
||||||
|
elif cmp == '=':
|
||||||
|
self.assertFalse(version_lt(ver1, ver2), msg=msg)
|
||||||
|
self.assertFalse(version_lt(ver2, ver1), msg=msg)
|
||||||
|
elif cmp == '>':
|
||||||
|
self.assertFalse(version_lt(ver1, ver2), msg=msg)
|
||||||
|
self.assertTrue(version_lt(ver2, ver1), msg=msg)
|
||||||
|
elif cmp == '?':
|
||||||
|
self.assertIsNone(version_lt(ver1, ver2), msg=msg)
|
||||||
|
self.assertIsNone(version_lt(ver2, ver1), msg=msg)
|
||||||
|
else:
|
||||||
|
assert False # nocoverage
|
||||||
|
|
||||||
class CompatibilityTest(ZulipTestCase):
|
class CompatibilityTest(ZulipTestCase):
|
||||||
def test_compatibility(self) -> None:
|
def test_compatibility(self) -> None:
|
||||||
|
|||||||
@@ -1,10 +1,53 @@
|
|||||||
|
|
||||||
from django.http import HttpResponse, HttpRequest
|
from django.http import HttpResponse, HttpRequest
|
||||||
from typing import Any, List, Dict, Optional
|
import re
|
||||||
|
from typing import Any, List, Dict, Optional, Tuple, Union
|
||||||
|
|
||||||
from zerver.lib.response import json_error, json_success
|
from zerver.lib.response import json_error, json_success
|
||||||
from zerver.lib.user_agent import parse_user_agent
|
from zerver.lib.user_agent import parse_user_agent
|
||||||
|
|
||||||
|
def pop_int(ver: str) -> Tuple[Optional[int], str]:
|
||||||
|
match = re.search(r'^(\d+)(.*)', ver)
|
||||||
|
if match is None:
|
||||||
|
return None, ver
|
||||||
|
return int(match.group(1)), match.group(2)
|
||||||
|
|
||||||
|
def version_lt(ver1: str, ver2: str) -> Optional[bool]:
|
||||||
|
'''
|
||||||
|
Compare two Zulip-style version strings.
|
||||||
|
|
||||||
|
Versions are dot-separated sequences of decimal integers,
|
||||||
|
followed by arbitrary trailing decoration. Comparison is
|
||||||
|
lexicographic on the integer sequences, and refuses to
|
||||||
|
guess how any trailing decoration compares to any other,
|
||||||
|
to further numerals, or to nothing.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if ver1 < ver2
|
||||||
|
False if ver1 >= ver2
|
||||||
|
None if can't tell.
|
||||||
|
'''
|
||||||
|
while True:
|
||||||
|
# Pull off the leading numeral from each version.
|
||||||
|
maj1, rest1 = pop_int(ver1)
|
||||||
|
maj2, rest2 = pop_int(ver2)
|
||||||
|
if maj1 is None or maj2 is None:
|
||||||
|
# One or both has no leading numeral; some unknown format.
|
||||||
|
return None
|
||||||
|
if maj1 < maj2:
|
||||||
|
return True
|
||||||
|
if maj1 > maj2:
|
||||||
|
return False
|
||||||
|
# Leading numerals are equal.
|
||||||
|
|
||||||
|
if rest1 == rest2:
|
||||||
|
return False
|
||||||
|
if not(rest1.startswith('.') and rest2.startswith('.')):
|
||||||
|
return None
|
||||||
|
ver1 = rest1[1:]
|
||||||
|
ver2 = rest2[1:]
|
||||||
|
|
||||||
|
|
||||||
def check_global_compatibility(request: HttpRequest) -> HttpResponse:
|
def check_global_compatibility(request: HttpRequest) -> HttpResponse:
|
||||||
user_agent = parse_user_agent(request.META["HTTP_USER_AGENT"])
|
user_agent = parse_user_agent(request.META["HTTP_USER_AGENT"])
|
||||||
if user_agent['name'] == "ZulipInvalid":
|
if user_agent['name'] == "ZulipInvalid":
|
||||||
|
|||||||
Reference in New Issue
Block a user