mirror of
https://github.com/f-droid/fdroidserver.git
synced 2026-09-14 06:57:40 -04:00
🧋 add array support for doante link metadata.
With this change the `Donate` metadata field can also be an array of links, not just one single link. e.g.: ``` Donate: - "https://f-droid.org/donate" - "https://donate.example.com/fdroid" ``` For backwards compatibility the old solo string format is also supported. e.g.: ``` Donate: "https://f-droid.org/donate" ```
This commit is contained in:
1 parent
ab268be1c8
commit
d7f52c4580
12 files changed
+59
-26
No files matched your search
@@ -61,6 +61,7 @@ metadata_v0:
|
||||
GIT_DEPTH: 1000
|
||||
RELEASE_COMMIT_ID: d172d991803b27ad5213d11b5a737e5cb9e5fc3a # after switching to `git rev-parse`
|
||||
script:
|
||||
- apt update -yyq && apt install -yyq yq
|
||||
- git fetch https://gitlab.com/fdroid/fdroidserver.git $RELEASE_COMMIT_ID
|
||||
- cd tests
|
||||
- export GITCOMMIT=$(git rev-parse HEAD)
|
||||
@@ -82,6 +83,10 @@ metadata_v0:
|
||||
metadata/dump_*/*.yaml
|
||||
# remove leading zeros (because we can't deal with that reliably)
|
||||
- 'sed -i ''s/: 0*\([1-9][0-9]*\)/: \1/g'' metadata/dump_*/*.yaml'
|
||||
# if .Donate is an array set .Donate to the first element in the array otherwise leave it unchanged
|
||||
# (running this in batches significantly speeds the gitlab.ci run)
|
||||
# TODO: remove this when tests need to migrate
|
||||
- find metadata/dump_*/ -name '*.yaml' -print0 | xargs -0 -P 4 -n 50 -- yq -y --in-place '.Donate |= if type == "array" then .[0] else . end'
|
||||
- diff -uw metadata/dump_*
|
||||
|
||||
.apt-template: &apt-template
|
||||
|
||||
+12
-2
@@ -607,7 +607,7 @@ def package_metadata(app, repodir):
|
||||
del meta["license"]
|
||||
|
||||
if app["Donate"]:
|
||||
meta["donate"] = [app["Donate"]]
|
||||
meta["donate"] = app["Donate"]
|
||||
|
||||
# TODO handle different resolutions
|
||||
if app.get("icon"):
|
||||
@@ -991,6 +991,9 @@ def make_v1(apps, packages, repodir, repodict, requestsdict, signer_fingerprints
|
||||
v = str(v)
|
||||
elif k == 'CurrentVersion': # TODO make SuggestedVersionName the canonical name
|
||||
k = 'suggestedVersionName'
|
||||
elif k == "Donate":
|
||||
k = "donate"
|
||||
v = _first(v)
|
||||
else:
|
||||
k = k[:1].lower() + k[1:]
|
||||
d[k] = v
|
||||
@@ -1327,7 +1330,7 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, signer_fingerprints):
|
||||
addElementNonEmpty('changelog', app.Changelog, doc, apel)
|
||||
addElementNonEmpty('author', app.AuthorName, doc, apel)
|
||||
addElementNonEmpty('email', app.AuthorEmail, doc, apel)
|
||||
addElementNonEmpty('donate', app.Donate, doc, apel)
|
||||
addElementNonEmpty('donate', _first(app.Donate), doc, apel)
|
||||
addElementNonEmpty('bitcoin', app.Bitcoin, doc, apel)
|
||||
addElementNonEmpty('litecoin', app.Litecoin, doc, apel)
|
||||
addElementNonEmpty('openCollective', app.OpenCollective, doc, apel)
|
||||
@@ -2116,3 +2119,10 @@ def make_altstore(apps, apks, config, repodir, pretty=False):
|
||||
|
||||
with open(Path(repodir) / 'altstore-index.json', "w", encoding="utf-8") as f:
|
||||
json.dump(idx, f, indent=indent)
|
||||
|
||||
|
||||
def _first(items, default_value=None):
|
||||
try:
|
||||
return items[0]
|
||||
except (IndexError, TypeError):
|
||||
return default_value
|
||||
@@ -1782,6 +1782,12 @@ def check_regexes(app):
|
||||
for line in v.splitlines():
|
||||
if m.match(line):
|
||||
yield "%s at line '%s': %s" % (f, line, r)
|
||||
elif t == metadata.TYPE_LIST:
|
||||
for item in v or []:
|
||||
if item is None:
|
||||
continue
|
||||
if m.match(item):
|
||||
yield "%s '%s': %s" % (f, item, r)
|
||||
else:
|
||||
if v is None:
|
||||
continue
|
||||
|
||||
@@ -126,7 +126,7 @@ class App(dict):
|
||||
self.IssueTracker = ''
|
||||
self.Translation = ''
|
||||
self.Changelog = ''
|
||||
self.Donate = None
|
||||
self.Donate = []
|
||||
self.Liberapay = None
|
||||
self.OpenCollective = None
|
||||
self.Bitcoin = None
|
||||
@@ -188,6 +188,7 @@ fieldtypes = {
|
||||
'MaintainerNotes': TYPE_MULTILINE,
|
||||
'Categories': TYPE_LIST,
|
||||
'AntiFeatures': TYPE_STRINGMAP,
|
||||
'Donate': TYPE_LIST,
|
||||
'RequiresRoot': TYPE_BOOL,
|
||||
'AllowedAPKSigningKeys': TYPE_LIST,
|
||||
'Builds': TYPE_BUILD,
|
||||
@@ -1269,6 +1270,11 @@ def _app_to_yaml(app):
|
||||
v = _format_stringmap(app['id'], field, value)
|
||||
if v:
|
||||
cm[field] = v
|
||||
elif field == 'Donate':
|
||||
if len(value) == 1:
|
||||
cm[field] = value[0]
|
||||
else:
|
||||
cm[field] = value
|
||||
elif field == 'AllowedAPKSigningKeys':
|
||||
value = [str(i).lower() for i in value]
|
||||
if len(value) == 1:
|
||||
|
||||
@@ -1052,44 +1052,44 @@ def insert_funding_yml_donation_links(apps):
|
||||
if k == 'custom':
|
||||
s = sanitize_funding_yml_entry(v)
|
||||
if s:
|
||||
app['Donate'] = s
|
||||
app['Donate'] = [s]
|
||||
break
|
||||
elif k in ('community_bridge', 'lfx_crowdfunding'):
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = (
|
||||
app['Donate'] = [
|
||||
f'https://crowdfunding.lfx.linuxfoundation.org/projects/{s}'
|
||||
)
|
||||
]
|
||||
break
|
||||
elif k == 'github':
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = 'https://github.com/sponsors/' + s
|
||||
app['Donate'] = ['https://github.com/sponsors/' + s]
|
||||
break
|
||||
elif k == 'issuehunt':
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = 'https://issuehunt.io/r/' + s
|
||||
app['Donate'] = ['https://issuehunt.io/r/' + s]
|
||||
break
|
||||
elif k == 'ko_fi':
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = 'https://ko-fi.com/' + s
|
||||
app['Donate'] = ['https://ko-fi.com/' + s]
|
||||
break
|
||||
elif k == 'patreon':
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = 'https://patreon.com/' + s
|
||||
app['Donate'] = ['https://patreon.com/' + s]
|
||||
break
|
||||
elif k == 'buy_me_a_coffee':
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = 'https://www.buymeacoffee.com/' + s
|
||||
app['Donate'] = ['https://www.buymeacoffee.com/' + s]
|
||||
break
|
||||
elif k == 'polar':
|
||||
s = sanitize_funding_yml_name(v)
|
||||
if s:
|
||||
app['Donate'] = 'https://polar.sh/' + s
|
||||
app['Donate'] = ['https://polar.sh/' + s]
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ Description: 'To configure, go to "Settings => Accounts & Sync => Add Account".
|
||||
|
||||
Appbrain SDK was removed before building.'
|
||||
Disabled: null
|
||||
Donate: null
|
||||
Donate: []
|
||||
IssueTracker: https://github.com/loadrunner/Facebook-Contact-Sync/issues
|
||||
Liberapay: null
|
||||
License: GPL-3.0-only
|
||||
|
||||
@@ -169,7 +169,7 @@ CurrentVersion: '1.5'
|
||||
CurrentVersionCode: 6
|
||||
Description: Activates silent mode during calendar events.
|
||||
Disabled: null
|
||||
Donate: null
|
||||
Donate: []
|
||||
IssueTracker: https://github.com/miguelvps/PoliteDroid/issues
|
||||
Liberapay: null
|
||||
License: GPL-3.0-only
|
||||
|
||||
@@ -1114,7 +1114,8 @@ Description: 'An ad blocker that uses the hosts file. The hosts file
|
||||
|
||||
read-only.'
|
||||
Disabled: null
|
||||
Donate: http://sufficientlysecure.org/index.php/adaway
|
||||
Donate:
|
||||
- http://sufficientlysecure.org/index.php/adaway
|
||||
IssueTracker: https://github.com/dschuermann/ad-away/issues
|
||||
Liberapay: null
|
||||
License: GPL-3.0-only
|
||||
|
||||
@@ -384,7 +384,7 @@ Description: 'SMSSecure is an SMS/MMS application that allows you to protect you
|
||||
* Open Source. SMSSecure is Free and Open Source, enabling anyone to verify its
|
||||
security by auditing the code.'
|
||||
Disabled: null
|
||||
Donate: null
|
||||
Donate: []
|
||||
IssueTracker: https://github.com/SMSSecure/SMSSecure/issues
|
||||
Liberapay: null
|
||||
License: GPL-3.0-only
|
||||
|
||||
@@ -2605,7 +2605,8 @@ Description: 'Video and audio player that supports a wide range of formats,
|
||||
|
||||
'
|
||||
Disabled: null
|
||||
Donate: http://www.videolan.org/contribute.html#money
|
||||
Donate:
|
||||
- http://www.videolan.org/contribute.html#money
|
||||
IssueTracker: http://www.videolan.org/support/index.html#bugs
|
||||
Liberapay: null
|
||||
License: GPL-3.0-only
|
||||
|
||||
+2
-2
@@ -179,13 +179,13 @@ class LintTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
|
||||
def test_check_regexes_donate(self):
|
||||
app = fdroidserver.metadata.App()
|
||||
app.Donate = 'https://example.com/donate/'
|
||||
app.Donate = ['https://example.com/donate/']
|
||||
for warn in fdroidserver.lint.check_regexes(app):
|
||||
self.fail()
|
||||
|
||||
def test_check_regexes_donate_both(self):
|
||||
app = fdroidserver.metadata.App()
|
||||
app.Donate = 'http://bit.ly/givememoney/'
|
||||
app.Donate = ['http://bit.ly/givememoney/']
|
||||
warns = list(fdroidserver.lint.check_regexes(app))
|
||||
for warn in warns:
|
||||
self.assertIn('bit.ly', warn)
|
||||
|
||||
+11
-7
@@ -1615,7 +1615,7 @@ class UpdateTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
'CurrentVersion': '',
|
||||
'CurrentVersionCode': None,
|
||||
'Disabled': '',
|
||||
'Donate': '',
|
||||
'Donate': None,
|
||||
'IssueTracker': '',
|
||||
'License': '',
|
||||
'Litecoin': '',
|
||||
@@ -1665,7 +1665,7 @@ class UpdateTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
fdroidserver.update.insert_funding_yml_donation_links(apps)
|
||||
for field in DONATION_FIELDS:
|
||||
self.assertIsNotNone(app.get(field), field)
|
||||
self.assertEqual('LINK1', app.get('Donate'))
|
||||
self.assertEqual(['LINK1'], app.get('Donate'))
|
||||
self.assertEqual('USERNAME', app.get('Liberapay'))
|
||||
self.assertEqual('USERNAME', app.get('OpenCollective'))
|
||||
|
||||
@@ -1686,8 +1686,9 @@ class UpdateTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
apps = {app.id: app}
|
||||
os.mkdir(os.path.join('build', app.id))
|
||||
fdroidserver.update.insert_funding_yml_donation_links(apps)
|
||||
for field in DONATION_FIELDS:
|
||||
self.assertIsNone(app.get(field))
|
||||
self.assertEqual(app.get("Donate"), [])
|
||||
self.assertIsNone(app.get("Liberapay"))
|
||||
self.assertIsNone(app.get("OpenCollective"))
|
||||
|
||||
content = textwrap.dedent(
|
||||
"""
|
||||
@@ -1715,8 +1716,10 @@ class UpdateTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
elif 'open_collective' in data:
|
||||
self.assertEqual(data['open_collective'], app.get('OpenCollective'))
|
||||
else:
|
||||
# 'Donate' metadata
|
||||
for v in data.values():
|
||||
self.assertEqual(app.get('Donate', '').split('/')[-1], v)
|
||||
for donate_option in app.get('Donate', []):
|
||||
self.assertEqual(donate_option.split('/')[-1], v)
|
||||
|
||||
def test_insert_funding_yml_donation_links_with_corrupt_file(self):
|
||||
os.chdir(self.testdir)
|
||||
@@ -1736,8 +1739,9 @@ class UpdateTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
)
|
||||
)
|
||||
fdroidserver.update.insert_funding_yml_donation_links(apps)
|
||||
for field in DONATION_FIELDS:
|
||||
self.assertIsNone(app.get(field))
|
||||
self.assertEqual(app.get("Donate"), [])
|
||||
self.assertIsNone(app.get("Liberapay"))
|
||||
self.assertIsNone(app.get("OpenCollective"))
|
||||
|
||||
def test_sanitize_funding_yml(self):
|
||||
with open(basedir / 'funding-usernames.yaml') as fp:
|
||||
|
||||
Reference in new issue
Block a user