Change VercodeOperation to list

... so that we can calculate multiple version codes to support multi-arch autoupdate
This commit is contained in:
linsui 2022-10-15 17:19:49 +08:00
parent 0d39169840
commit 68b58c043f
3 changed files with 122 additions and 47 deletions

View File

@ -379,7 +379,6 @@ def _getcvname(app):
def fetch_autoname(app, tag):
if not app.RepoType or app.UpdateCheckMode in ('None', 'Static') \
or app.UpdateCheckName == "Ignore":
return None
@ -417,14 +416,23 @@ def fetch_autoname(app, tag):
return commitmsg
def checkupdates_app(app):
def operate_vercode(operation, vercode):
if not common.VERCODE_OPERATION_RE.match(operation):
raise MetaDataException(_('Invalid VercodeOperation: {field}')
.format(field=operation))
oldvercode = vercode
op = operation.replace("%c", str(oldvercode))
vercode = common.calculate_math_string(op)
logging.debug("Applied vercode operation: %d -> %d" % (oldvercode, vercode))
return vercode
def checkupdates_app(app):
# If a change is made, commitmsg should be set to a description of it.
# Only if this is set will changes be written back to the metadata.
commitmsg = None
tag = None
vercode = None
mode = app.UpdateCheckMode
if mode.startswith('Tags'):
pattern = mode[5:] if len(mode) > 4 else None
@ -444,30 +452,33 @@ def checkupdates_app(app):
else:
raise MetaDataException(_('Invalid UpdateCheckMode: {mode}').format(mode=mode))
if version and vercode and app.VercodeOperation:
if not common.VERCODE_OPERATION_RE.match(app.VercodeOperation):
raise MetaDataException(_('Invalid VercodeOperation: {field}')
.format(field=app.VercodeOperation))
oldvercode = str(int(vercode))
op = app.VercodeOperation.replace("%c", oldvercode)
vercode = str(common.calculate_math_string(op))
logging.debug("Applied vercode operation: %s -> %s" % (oldvercode, vercode))
if not version or not vercode:
raise FDroidException(_('no version information found'))
if app.VercodeOperation:
if isinstance(app.VercodeOperation, str):
vercodes = [operate_vercode(app.VercodeOperation, vercode)]
else:
vercodes = sorted([
operate_vercode(operation, vercode)
for operation in app.VercodeOperation
])
else:
vercodes = [vercode]
updating = False
if version is None:
raise FDroidException(_('no version information found'))
elif vercode == app.CurrentVersionCode:
if vercodes[-1] == app.CurrentVersionCode:
logging.debug("...up to date")
elif vercode > app.CurrentVersionCode:
elif vercodes[-1] > app.CurrentVersionCode:
logging.debug("...updating - old vercode={0}, new vercode={1}".format(
app.CurrentVersionCode, vercode))
app.CurrentVersionCode, vercodes[-1]))
app.CurrentVersion = version
app.CurrentVersionCode = vercode
app.CurrentVersionCode = vercodes[-1]
updating = True
else:
raise FDroidException(
_('current version is newer: old vercode={old}, new vercode={new}').format(
old=app.CurrentVersionCode, new=vercode
old=app.CurrentVersionCode, new=vercodes[-1]
)
)
@ -498,35 +509,38 @@ def checkupdates_app(app):
gotcur = False
latest = None
for build in app.get('Builds', []):
if build.versionCode >= app.CurrentVersionCode:
gotcur = True
if not latest or build.versionCode > latest.versionCode:
latest = build
builds = app.get('Builds', [])
if latest.versionCode > app.CurrentVersionCode:
raise FDroidException(
_(
'latest build recipe is newer: old vercode={old}, new vercode={new}'
).format(old=latest.versionCode, new=app.CurrentVersionCode)
)
if builds:
latest = builds[-1]
if latest.versionCode == app.CurrentVersionCode:
gotcur = True
elif latest.versionCode > app.CurrentVersionCode:
raise FDroidException(
_(
'latest build recipe is newer: '
'old vercode={old}, new vercode={new}'
).format(old=latest.versionCode, new=app.CurrentVersionCode)
)
if not gotcur:
newbuild = copy.deepcopy(latest)
newbuild.disable = False
newbuild.versionCode = app.CurrentVersionCode
newbuild.versionName = app.CurrentVersion + suffix.replace(
'%c', str(newbuild.versionCode)
)
logging.info("...auto-generating build for " + newbuild.versionName)
if tag:
newbuild.commit = tag
else:
commit = pattern.replace('%v', str(app.CurrentVersion))
commit = commit.replace('%c', str(newbuild.versionCode))
newbuild.commit = commit
newbuilds = copy.deepcopy(builds[-len(vercodes):])
for b, v in zip(newbuilds, vercodes):
b.disable = False
b.versionCode = v
b.versionName = app.CurrentVersion + suffix.replace(
'%c', str(v)
)
logging.info("...auto-generating build for " + b.versionName)
if tag:
b.commit = tag
else:
commit = pattern.replace('%v', app.CurrentVersion)
commit = commit.replace('%c', str(v))
b.commit = commit
app['Builds'].extend(newbuilds)
app['Builds'].append(newbuild)
name = _getappname(app)
ver = _getcvname(app)
commitmsg = "Update %s to %s" % (name, ver)

View File

@ -262,10 +262,21 @@ def check_update_check_data_url(app): # noqa: D403
def check_vercode_operation(app):
if app.VercodeOperation and not common.VERCODE_OPERATION_RE.match(
app.VercodeOperation
):
yield _('Invalid VercodeOperation: {field}').format(field=app.VercodeOperation)
if not app.VercodeOperation:
return
ops = (
[app.VercodeOperation]
if isinstance(app.VercodeOperation, str)
else app.VercodeOperation
)
invalid_ops = []
for op in ops:
if not common.VERCODE_OPERATION_RE.match(op):
invalid_ops += op
if invalid_ops:
yield _('Invalid VercodeOperation: {invalid_ops}').format(
invalid_ops=invalid_ops
)
def check_ucm_tags(app):

View File

@ -102,6 +102,56 @@ class CheckupdatesTest(unittest.TestCase):
self.assertEqual(build.versionName, '1.1.9.10109-fdroid')
self.assertEqual(build.commit, 'v1.1.9_10109')
def test_autoupdate_multi_variants(self):
fdroidserver.checkupdates.options = mock.Mock()
fdroidserver.checkupdates.options.auto = 'bleh'
fdroidserver.checkupdates.config = {}
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersion = '1.1.8'
app.CurrentVersionCode = 101083
app.UpdateCheckMode = 'Tags'
app.AutoUpdateMode = r'Version'
app.VercodeOperation = [
"10*%c+1",
"10*%c+3",
]
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode - 2
build.versionName = app.CurrentVersion
build.gradle = ["arm"]
app['Builds'].append(build)
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode
build.versionName = app.CurrentVersion
build.gradle = ["x86"]
app['Builds'].append(build)
with mock.patch(
'fdroidserver.checkupdates.check_tags',
lambda app, pattern: ('1.1.9', 10109, 'v1.1.9'),
):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0):
fdroidserver.checkupdates.checkupdates_app(app)
build = app['Builds'][-2]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.versionCode, 101091)
self.assertEqual(build.gradle, ["arm"])
build = app['Builds'][-1]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.versionCode, 101093)
self.assertEqual(build.gradle, ["x86"])
self.assertEqual(app.CurrentVersion, '1.1.9')
self.assertEqual(app.CurrentVersionCode, 101093)
def test_checkupdates_app_http(self):
fdroidserver.checkupdates.options = mock.Mock()
fdroidserver.checkupdates.options.auto = 'bleh'