1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-11-20 13:50:12 +01:00

Merge branch 'autoname-only-in-checkupdates' into 'master'

AutoName: only in checkupdates

Closes #654

See merge request fdroid/fdroidserver!759
This commit is contained in:
Hans-Christoph Steiner 2021-01-15 13:24:19 +00:00
commit 6ec23388ce
13 changed files with 337 additions and 63 deletions

View File

@ -326,7 +326,7 @@ def try_init_submodules(app, last_build, vcs):
try: try:
vcs.initsubmodules() vcs.initsubmodules()
except NoSubmodulesException: except NoSubmodulesException:
logging.info("No submodules present for {}".format(app.Name)) logging.info("No submodules present for {}".format(_getappname(app)))
# Return all directories under startdir that contain any of the manifest # Return all directories under startdir that contain any of the manifest
@ -359,11 +359,7 @@ def possible_subdirs(app):
def _getappname(app): def _getappname(app):
if app.Name: return common.get_app_display_name(app)
return app.Name
if app.AutoName:
return app.AutoName
return app.id
def _getcvname(app): def _getcvname(app):

View File

@ -3511,9 +3511,9 @@ def get_certificate(signature_block_file):
def load_stats_fdroid_signing_key_fingerprints(): def load_stats_fdroid_signing_key_fingerprints():
"""Load list of signing-key fingerprints stored by fdroid publish from file. """Load signing-key fingerprints stored in file generated by fdroid publish.
:returns: list of dictionanryies containing the singing-key fingerprints. :returns: dict containing the signing-key fingerprints.
""" """
jar_file = os.path.join('stats', 'publishsigkeys.jar') jar_file = os.path.join('stats', 'publishsigkeys.jar')
if not os.path.isfile(jar_file): if not os.path.isfile(jar_file):
@ -3628,6 +3628,26 @@ def version_code_string_to_int(vercode):
return int(vercode) return int(vercode)
def get_app_display_name(app):
"""get a human readable name for the app for logging and sorting
When trying to find a localized name, this first tries en-US since
that his the historical language used for sorting.
"""
if app.get('Name'):
return app['Name']
if app.get('localized'):
localized = app['localized'].get('en-US')
if not localized:
for v in app['localized'].values():
localized = v
break
if localized.get('name'):
return localized['name']
return app.get('AutoName') or app['id']
def local_rsync(options, fromdir, todir): def local_rsync(options, fromdir, todir):
'''Rsync method for local to local copying of things '''Rsync method for local to local copying of things

View File

@ -61,7 +61,7 @@ def make(apps, apks, repodir, archive):
common.assert_config_keystore(common.config) common.assert_config_keystore(common.config)
# Historically the index has been sorted by App Name, so we enforce this ordering here # Historically the index has been sorted by App Name, so we enforce this ordering here
sortedids = sorted(apps, key=lambda appid: apps[appid]['Name'].upper()) sortedids = sorted(apps, key=lambda appid: common.get_app_display_name(apps[appid]).upper())
sortedapps = collections.OrderedDict() sortedapps = collections.OrderedDict()
for appid in sortedids: for appid in sortedids:
sortedapps[appid] = apps[appid] sortedapps[appid] = apps[appid]
@ -159,7 +159,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict, fdroid_signing_key_
if not v: if not v:
continue continue
if k in ('Builds', 'comments', 'metadatapath', if k in ('Builds', 'comments', 'metadatapath',
'ArchivePolicy', 'AutoUpdateMode', 'MaintainerNotes', 'ArchivePolicy', 'AutoName', 'AutoUpdateMode', 'MaintainerNotes',
'Provides', 'Repo', 'RepoType', 'RequiresRoot', 'Provides', 'Repo', 'RepoType', 'RequiresRoot',
'UpdateCheckData', 'UpdateCheckIgnore', 'UpdateCheckMode', 'UpdateCheckData', 'UpdateCheckIgnore', 'UpdateCheckMode',
'UpdateCheckName', 'NoSourceSince', 'VercodeOperation'): 'UpdateCheckName', 'NoSourceSince', 'VercodeOperation'):
@ -172,10 +172,6 @@ def make_v1(apps, packages, repodir, repodict, requestsdict, fdroid_signing_key_
k = 'suggestedVersionCode' k = 'suggestedVersionCode'
elif k == 'CurrentVersion': # TODO make SuggestedVersionName the canonical name elif k == 'CurrentVersion': # TODO make SuggestedVersionName the canonical name
k = 'suggestedVersionName' k = 'suggestedVersionName'
elif k == 'AutoName':
if 'Name' not in apps[packageName]:
d['name'] = v
continue
else: else:
k = k[:1].lower() + k[1:] k = k[:1].lower() + k[1:]
d[k] = v d[k] = v
@ -326,6 +322,8 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
value = localized[lang].get(lkey) value = localized[lang].get(lkey)
if not value: if not value:
value = default value = default
if not value and name == 'name' and app.get('AutoName'):
value = app['AutoName']
el.appendChild(doc.createTextNode(value)) el.appendChild(doc.createTextNode(value))
parent.appendChild(el) parent.appendChild(el)
@ -363,10 +361,13 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
# Get a list of the apks for this app... # Get a list of the apks for this app...
apklist = [] apklist = []
name_from_apk = None
apksbyversion = collections.defaultdict(lambda: []) apksbyversion = collections.defaultdict(lambda: [])
for apk in apks: for apk in apks:
if apk.get('versionCode') and apk.get('packageName') == appid: if apk.get('versionCode') and apk.get('packageName') == appid:
apksbyversion[apk['versionCode']].append(apk) apksbyversion[apk['versionCode']].append(apk)
if name_from_apk is None:
name_from_apk = apk.get('name')
for versionCode, apksforver in apksbyversion.items(): for versionCode, apksforver in apksbyversion.items():
fdroidsig = fdroid_signing_key_fingerprints.get(appid, {}).get('signer') fdroidsig = fdroid_signing_key_fingerprints.get(appid, {}).get('signer')
fdroid_signed_apk = None fdroid_signed_apk = None
@ -398,7 +399,7 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
if app.lastUpdated: if app.lastUpdated:
addElement('lastupdated', app.lastUpdated.strftime('%Y-%m-%d'), doc, apel) addElement('lastupdated', app.lastUpdated.strftime('%Y-%m-%d'), doc, apel)
addElementCheckLocalized('name', app, 'Name', doc, apel) addElementCheckLocalized('name', app, 'Name', doc, apel, name_from_apk)
addElementCheckLocalized('summary', app, 'Summary', doc, apel) addElementCheckLocalized('summary', app, 'Summary', doc, apel)
if app.icon: if app.icon:
@ -466,10 +467,10 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
for apk in apklist: for apk in apklist:
file_extension = common.get_file_extension(apk['apkName']) file_extension = common.get_file_extension(apk['apkName'])
# find the APK for the "Current Version" # find the APK for the "Current Version"
if current_version_code < apk['versionCode']:
current_version_code = apk['versionCode']
if current_version_code < int(app.CurrentVersionCode): if current_version_code < int(app.CurrentVersionCode):
current_version_file = apk['apkName'] current_version_file = apk['apkName']
if current_version_code < apk['versionCode']:
current_version_code = apk['versionCode']
apkel = doc.createElement("package") apkel = doc.createElement("package")
apel.appendChild(apkel) apel.appendChild(apkel)
@ -543,7 +544,12 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
and common.config['make_current_version_link'] \ and common.config['make_current_version_link'] \
and repodir == 'repo': # only create these and repodir == 'repo': # only create these
namefield = common.config['current_version_name_source'] namefield = common.config['current_version_name_source']
sanitized_name = re.sub(b'''[ '"&%?+=/]''', b'', app.get(namefield).encode('utf-8')) name = app.get(namefield)
if not name and namefield == 'Name':
name = app.get('localized', {}).get('en-US', {}).get('name')
if not name:
name = app.id
sanitized_name = re.sub(b'''[ '"&%?+=/]''', b'', name.encode('utf-8'))
apklinkname = sanitized_name + os.path.splitext(current_version_file)[1].encode('utf-8') apklinkname = sanitized_name + os.path.splitext(current_version_file)[1].encode('utf-8')
current_version_path = os.path.join(repodir, current_version_file).encode('utf-8', 'surrogateescape') current_version_path = os.path.join(repodir, current_version_file).encode('utf-8', 'surrogateescape')
if os.path.islink(apklinkname): if os.path.islink(apklinkname):

View File

@ -323,9 +323,6 @@ def check_categories(app):
def check_duplicates(app): def check_duplicates(app):
if app.Name and app.Name == app.AutoName:
yield _("Name '%s' is just the auto name - remove it") % app.Name
links_seen = set() links_seen = set()
for f in ['Source Code', 'Web Site', 'Issue Tracker', 'Changelog']: for f in ['Source Code', 'Web Site', 'Issue Tracker', 'Changelog']:
v = app.get(f) v = app.get(f)
@ -337,7 +334,7 @@ def check_duplicates(app):
else: else:
links_seen.add(v) links_seen.add(v)
name = app.Name or app.AutoName name = common.get_app_display_name(app)
if app.Summary and name: if app.Summary and name:
if app.Summary.lower() == name.lower(): if app.Summary.lower() == name.lower():
yield _("Summary '%s' is just the app's name") % app.Summary yield _("Summary '%s' is just the app's name") % app.Summary

View File

@ -207,9 +207,12 @@ def update_wiki(apps, apks):
requiresroot = 'Yes' requiresroot = 'Yes'
else: else:
requiresroot = 'No' requiresroot = 'No'
apppagename = common.get_app_display_name(app)
wikidata += '{{App|id=%s|name=%s|added=%s|lastupdated=%s|source=%s|tracker=%s|web=%s|changelog=%s|donate=%s|flattr=%s|liberapay=%s|bitcoin=%s|litecoin=%s|license=%s|root=%s|author=%s|email=%s}}\n' % ( wikidata += '{{App|id=%s|name=%s|added=%s|lastupdated=%s|source=%s|tracker=%s|web=%s|changelog=%s|donate=%s|flattr=%s|liberapay=%s|bitcoin=%s|litecoin=%s|license=%s|root=%s|author=%s|email=%s}}\n' % (
appid, appid,
app.Name, apppagename,
app.added.strftime('%Y-%m-%d') if app.added else '', app.added.strftime('%Y-%m-%d') if app.added else '',
app.lastUpdated.strftime('%Y-%m-%d') if app.lastUpdated else '', app.lastUpdated.strftime('%Y-%m-%d') if app.lastUpdated else '',
app.SourceCode, app.SourceCode,
@ -338,7 +341,6 @@ def update_wiki(apps, apks):
# Make a redirect from the name to the ID too, unless there's # Make a redirect from the name to the ID too, unless there's
# already an existing page with the name and it isn't a redirect. # already an existing page with the name and it isn't a redirect.
noclobber = False noclobber = False
apppagename = app.Name
for ch in '_{}:[]|': for ch in '_{}:[]|':
apppagename = apppagename.replace(ch, ' ') apppagename = apppagename.replace(ch, ' ')
# Drop double spaces caused mostly by replacing ':' above # Drop double spaces caused mostly by replacing ':' above
@ -1903,15 +1905,10 @@ def apply_info_from_latest_apk(apps, apks):
logging.debug("Don't know when " + appid + " was last updated") logging.debug("Don't know when " + appid + " was last updated")
if bestver == UNSET_VERSION_CODE: if bestver == UNSET_VERSION_CODE:
if app.get('Name') is None:
app['Name'] = app['AutoName'] or appid
app['icon'] = None app['icon'] = None
logging.debug("Application " + appid + " has no packages") logging.debug("Application " + appid + " has no packages")
else: else:
if app.get('Name') is None: app.icon = bestapk['icon'] if 'icon' in bestapk else None
app['Name'] = bestapk['name']
app['icon'] = bestapk['icon'] if 'icon' in bestapk else None
if app.get('CurrentVersionCode') is None: if app.get('CurrentVersionCode') is None:
app['CurrentVersionCode'] = str(bestver) app['CurrentVersionCode'] = str(bestver)
@ -2104,23 +2101,45 @@ def read_added_date_from_all_apks(apps, apks):
app['lastUpdated'] = apk['added'] app['lastUpdated'] = apk['added']
def read_names_from_apks(apps, apks): def insert_missing_app_names_from_apks(apps, apks):
"""This is a stripped down copy of apply_info_from_latest_apk that only parses app names""" """Use app name from APK if it is not set in the metadata
Name -> localized -> from APK
The name from the APK is set as the default name for the app if
there is no other default set, e.g. app['Name'] or
app['localized']['en-US']['name']. The en-US locale is defined in
the F-Droid ecosystem as the locale of last resort, as in the one
that should always be present. en-US is used since it is the
locale of the source strings.
This should only be used for index v0 and v1. Later versions of
the index should be sorted by Application ID, since it is
guaranteed to always be there. Before, the index was stored by
the app name (aka <application android:label="">) to save the
website from having to sort the entries. That is no longer
relevant since the website switched from Wordpress to Jekyll.
"""
for appid, app in apps.items(): for appid, app in apps.items():
if app.get('Name') is not None:
continue
if app.get('localized', {}).get('en-US', {}).get('name') is not None:
continue
bestver = UNSET_VERSION_CODE bestver = UNSET_VERSION_CODE
for apk in apks: for apk in apks:
if apk['packageName'] == appid: if apk['packageName'] == appid:
if apk['versionCode'] > bestver: if apk.get('name') and apk['versionCode'] > bestver:
bestver = apk['versionCode'] bestver = apk['versionCode']
bestapk = apk bestapk = apk
if bestver == UNSET_VERSION_CODE: if bestver != UNSET_VERSION_CODE:
if app.Name is None: if 'localized' not in app:
app.Name = app.AutoName or appid app['localized'] = {}
app.icon = None if 'en-US' not in app['localized']:
else: app['localized']['en-US'] = {}
if app.Name is None: app['localized']['en-US']['name'] = bestapk.get('name')
app.Name = bestapk['name']
def get_apps_with_packages(apps, apks): def get_apps_with_packages(apps, apks):
@ -2159,6 +2178,7 @@ def prepare_apps(apps, apks, repodir):
translate_per_build_anti_features(apps_with_packages, apks) translate_per_build_anti_features(apps_with_packages, apks)
if repodir == 'repo': if repodir == 'repo':
insert_localized_app_metadata(apps_with_packages) insert_localized_app_metadata(apps_with_packages)
insert_missing_app_names_from_apks(apps_with_packages, apks)
return apps_with_packages return apps_with_packages
@ -2305,11 +2325,9 @@ def main():
else: else:
archapks = [] archapks = []
# We need app.Name populated for all apps regardless of which repo they end up in if cachechanged:
# for the old-style inter-app links, so let's do it before we do anything else. write_cache(apkcache)
# This will be done again (as part of apply_info_from_latest_apk) for repo and archive
# separately later on, but it's fairly cheap anyway.
read_names_from_apks(apps, apks + archapks)
# The added date currently comes from the oldest apk which might be in the archive. # The added date currently comes from the oldest apk which might be in the archive.
# So we need this populated at app level before continuing with only processing /repo # So we need this populated at app level before continuing with only processing /repo
# or /archive # or /archive
@ -2349,9 +2367,6 @@ def main():
# Update known apks info... # Update known apks info...
knownapks.writeifchanged() knownapks.writeifchanged()
if cachechanged:
write_cache(apkcache)
# Update the wiki... # Update the wiki...
if options.wiki: if options.wiki:
logging.warning(_('wiki support is deprecated and will be removed in the next release!')) logging.warning(_('wiki support is deprecated and will be removed in the next release!'))

View File

@ -1612,6 +1612,21 @@ class CommonTest(unittest.TestCase):
self.assertEqual([dirtyfile, 'repo/status/running.json'], self.assertEqual([dirtyfile, 'repo/status/running.json'],
data['fdroiddata']['untrackedFiles']) data['fdroiddata']['untrackedFiles'])
def test_get_app_display_name(self):
testvalue = 'WIN!'
for app in [
{'Name': testvalue},
{'AutoName': testvalue},
{'id': testvalue},
{'id': 'a', 'localized': {'de-AT': {'name': testvalue}}},
{'id': 'a', 'localized': {
'de-AT': {'name': 'nope'},
'en-US': {'name': testvalue},
}},
{'AutoName': 'ignore me', 'Name': testvalue, 'id': 'nope'},
{'AutoName': testvalue, 'id': 'nope'}]:
self.assertEqual(testvalue, fdroidserver.common.get_app_display_name(app))
if __name__ == "__main__": if __name__ == "__main__":
os.chdir(os.path.dirname(__file__)) os.chdir(os.path.dirname(__file__))

View File

@ -247,7 +247,7 @@ class IndexTest(unittest.TestCase):
self.maxDiff = None self.maxDiff = None
self.assertEqual(json.dumps(i, indent=2), json.dumps(o, indent=2)) self.assertEqual(json.dumps(i, indent=2), json.dumps(o, indent=2))
def test_make_v0(self): def test_make_v0_repo_only(self):
tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name, tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
dir=self.tmpdir) dir=self.tmpdir)
os.chdir(tmptestsdir) os.chdir(tmptestsdir)
@ -264,7 +264,71 @@ class IndexTest(unittest.TestCase):
} }
requestsdict = {'install': [], 'uninstall': []} requestsdict = {'install': [], 'uninstall': []}
fdroidserver.common.config['repo_pubkey'] = 'ffffffffffffffffffffffffffffffffff' fdroidserver.common.config['repo_pubkey'] = 'ffffffffffffffffffffffffffffffffff'
fdroidserver.index.make_v0({}, [], 'repo', repodict, requestsdict, []) fdroidserver.index.make_v0({}, [], 'repo', repodict, requestsdict, {})
self.assertTrue(os.path.isdir(repo_icons_dir))
self.assertTrue(os.path.exists(os.path.join(repo_icons_dir,
fdroidserver.common.default_config['repo_icon'])))
self.assertTrue(os.path.exists(os.path.join('repo', 'index.xml')))
def test_make_v0(self):
tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
dir=self.tmpdir)
os.chdir(tmptestsdir)
os.mkdir('metadata')
os.mkdir('repo')
metadatafile = 'metadata/info.zwanenburg.caffeinetile.yml'
shutil.copy(os.path.join(self.basedir, metadatafile),
metadatafile)
repo_icons_dir = os.path.join('repo', 'icons')
self.assertFalse(os.path.isdir(repo_icons_dir))
repodict = {
'address': 'https://example.com/fdroid/repo',
'description': 'This is just a test',
'icon': 'blahblah',
'name': 'test',
'timestamp': datetime.datetime.now(),
'version': 12,
}
app = fdroidserver.metadata.parse_metadata(metadatafile, False, False)
app['icon'] = 'info.zwanenburg.caffeinetile.4.xml'
app['CurrentVersionCode'] = '4'
apps = {app.id: app}
apk = {
'hash': 'dbbdd7deadb038862f426b71efe4a64df8c3edf25d669e935f349510e16f65db',
'hashType': 'sha256',
'uses-permission': [
[
'android.permission.WAKE_LOCK',
None
]
],
'uses-permission-sdk-23': [],
'features': [],
'icons_src': {
'160': 'res/drawable/ic_coffee_on.xml',
'-1': 'res/drawable/ic_coffee_on.xml'
},
'icons': {
'160': 'info.zwanenburg.caffeinetile.4.xml'
},
'antiFeatures': [],
'packageName': 'info.zwanenburg.caffeinetile',
'versionCode': 4,
'name': 'Caffeine Tile',
'versionName': '1.3',
'minSdkVersion': 24,
'targetSdkVersion': 25,
'sig': '03f9b2f848d22fd1d8d1331e8b1b486d',
'signer': '51cfa5c8a743833ad89acf81cb755936876a5c8b8eca54d1ffdcec0cdca25d0e',
'size': 11740,
'apkName': 'info.zwanenburg.caffeinetile_4.apk',
'icon': 'info.zwanenburg.caffeinetile.4.xml',
'added': datetime.datetime.fromtimestamp(1539122400),
}
requestsdict = {'install': [], 'uninstall': []}
fdroidserver.common.config['repo_pubkey'] = 'ffffffffffffffffffffffffffffffffff'
fdroidserver.common.config['make_current_version_link'] = True
fdroidserver.index.make_v0(apps, [apk], 'repo', repodict, requestsdict, {})
self.assertTrue(os.path.isdir(repo_icons_dir)) self.assertTrue(os.path.isdir(repo_icons_dir))
self.assertTrue(os.path.exists(os.path.join(repo_icons_dir, self.assertTrue(os.path.exists(os.path.join(repo_icons_dir,
fdroidserver.common.default_config['repo_icon']))) fdroidserver.common.default_config['repo_icon'])))

View File

@ -9,6 +9,7 @@ Translation: https://www.transifex.com/otf/checkey
Bitcoin: 1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk Bitcoin: 1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk
Liberapay: GuardianProject Liberapay: GuardianProject
Name: Checkey the app!
AutoName: Checkey AutoName: Checkey
AutoUpdateMode: None AutoUpdateMode: None

View File

@ -0,0 +1 @@
Checkey: info on local apps

View File

@ -0,0 +1 @@
Checkey: ローカルアプリの情報

View File

@ -32,14 +32,18 @@
"flattrID": "cad90e036b975ed129a3ce80a0750466", "flattrID": "cad90e036b975ed129a3ce80a0750466",
"issueTracker": "https://gitlab.com/souch/SMSbypass/issues", "issueTracker": "https://gitlab.com/souch/SMSbypass/issues",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"name": "Battery level",
"sourceCode": "https://gitlab.com/souch/SMSbypass/tree/HEAD", "sourceCode": "https://gitlab.com/souch/SMSbypass/tree/HEAD",
"summary": "Filter SMS and show them in a fake app", "summary": "Filter SMS and show them in a fake app",
"webSite": "https://gitlab.com/souch/SMSbypass", "webSite": "https://gitlab.com/souch/SMSbypass",
"added": 1524700800000, "added": 1524700800000,
"icon": "souch.smsbypass.9.png", "icon": "souch.smsbypass.9.png",
"packageName": "souch.smsbypass", "packageName": "souch.smsbypass",
"lastUpdated": 1524700800000 "lastUpdated": 1524700800000,
"localized": {
"en-US": {
"name": "Battery level"
}
}
}, },
{ {
"categories": [ "categories": [
@ -77,13 +81,17 @@
"donate": "https://f-droid.org/about", "donate": "https://f-droid.org/about",
"issueTracker": "https://gitlab.com/fdroid/privileged-extension/issues", "issueTracker": "https://gitlab.com/fdroid/privileged-extension/issues",
"license": "Apache-2.0", "license": "Apache-2.0",
"name": "fake.ota.update_1234",
"sourceCode": "https://gitlab.com/fdroid/privileged-extension", "sourceCode": "https://gitlab.com/fdroid/privileged-extension",
"summary": "Tests whether OTA ZIP files are being include", "summary": "Tests whether OTA ZIP files are being include",
"webSite": "https://f-droid.org", "webSite": "https://f-droid.org",
"added": 1457568000000, "added": 1457568000000,
"packageName": "fake.ota.update", "packageName": "fake.ota.update",
"lastUpdated": 1457568000000 "lastUpdated": 1457568000000,
"localized": {
"en-US": {
"name": "fake.ota.update_1234"
}
}
}, },
{ {
"categories": [ "categories": [
@ -106,12 +114,16 @@
"suggestedVersionCode": "99999999", "suggestedVersionCode": "99999999",
"liberapay": "12334", "liberapay": "12334",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"name": "OBB Main Old Version",
"sourceCode": "https://github.com/eighthave/urzip", "sourceCode": "https://github.com/eighthave/urzip",
"added": 1388448000000, "added": 1388448000000,
"icon": "obb.main.oldversion.1444412523.png", "icon": "obb.main.oldversion.1444412523.png",
"packageName": "obb.main.oldversion", "packageName": "obb.main.oldversion",
"lastUpdated": 1388448000000 "lastUpdated": 1388448000000,
"localized": {
"en-US": {
"name": "OBB Main Old Version"
}
}
}, },
{ {
"bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk", "bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk",
@ -120,12 +132,16 @@
], ],
"suggestedVersionCode": "99999999", "suggestedVersionCode": "99999999",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"name": "OBB Main Two Versions",
"sourceCode": "https://github.com/eighthave/urzip", "sourceCode": "https://github.com/eighthave/urzip",
"added": 1444608000000, "added": 1444608000000,
"icon": "obb.main.twoversions.1101617.png", "icon": "obb.main.twoversions.1101617.png",
"packageName": "obb.main.twoversions", "packageName": "obb.main.twoversions",
"lastUpdated": 1466380800000 "lastUpdated": 1466380800000,
"localized": {
"en-US": {
"name": "OBB Main Two Versions"
}
}
}, },
{ {
"bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk", "bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk",
@ -134,7 +150,6 @@
], ],
"suggestedVersionCode": "99999999", "suggestedVersionCode": "99999999",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"name": "OBB Main/Patch Current",
"sourceCode": "https://github.com/eighthave/urzip", "sourceCode": "https://github.com/eighthave/urzip",
"added": 1461369600000, "added": 1461369600000,
"icon": "obb.mainpatch.current.1619.png", "icon": "obb.mainpatch.current.1619.png",
@ -144,6 +159,7 @@
"en-US": { "en-US": {
"featureGraphic": "featureGraphic_ffhLaojxbGAfu9ROe1MJgK5ux8d0OVc6b65nmvOBaTk=.png", "featureGraphic": "featureGraphic_ffhLaojxbGAfu9ROe1MJgK5ux8d0OVc6b65nmvOBaTk=.png",
"icon": "icon_WI0pkO3LsklrsTAnRr-OQSxkkoMY41lYe2-fAvXLiLg=.png", "icon": "icon_WI0pkO3LsklrsTAnRr-OQSxkkoMY41lYe2-fAvXLiLg=.png",
"name": "OBB Main/Patch Current",
"phoneScreenshots": [ "phoneScreenshots": [
"screenshot-main.png" "screenshot-main.png"
], ],
@ -165,13 +181,17 @@
"description": "Activates silent mode during calendar events.", "description": "Activates silent mode during calendar events.",
"issueTracker": "https://github.com/miguelvps/PoliteDroid/issues", "issueTracker": "https://github.com/miguelvps/PoliteDroid/issues",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"name": "Polite Droid",
"sourceCode": "https://github.com/miguelvps/PoliteDroid", "sourceCode": "https://github.com/miguelvps/PoliteDroid",
"summary": "Calendar tool", "summary": "Calendar tool",
"added": 1498176000000, "added": 1498176000000,
"icon": "com.politedroid.6.png", "icon": "com.politedroid.6.png",
"packageName": "com.politedroid", "packageName": "com.politedroid",
"lastUpdated": 1498176000000 "lastUpdated": 1498176000000,
"localized": {
"en-US": {
"name": "Polite Droid"
}
}
}, },
{ {
"authorWebSite": "https://guardianproject.info", "authorWebSite": "https://guardianproject.info",
@ -187,7 +207,6 @@
"issueTracker": "https://dev.guardianproject.info/projects/urzip/issues", "issueTracker": "https://dev.guardianproject.info/projects/urzip/issues",
"liberapayID": "9999999", "liberapayID": "9999999",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"name": "urzip-\u03c0\u00c7\u00c7\u03c0\u00c7\u00c7\u73b0\u4ee3\u6c49\u8bed\u901a\u7528\u5b57-\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438-\u0639\u0631\u0628\u064a1234",
"openCollective": "f-droid-just-testing", "openCollective": "f-droid-just-testing",
"sourceCode": "https://github.com/guardianproject/urzip", "sourceCode": "https://github.com/guardianproject/urzip",
"summary": "\u4e00\u4e2a\u5b9e\u7528\u5de5\u5177\uff0c\u83b7\u53d6\u5df2\u5b89\u88c5\u5728\u60a8\u7684\u8bbe\u5907\u4e0a\u7684\u5e94\u7528\u7684\u6709\u5173\u4fe1\u606f", "summary": "\u4e00\u4e2a\u5b9e\u7528\u5de5\u5177\uff0c\u83b7\u53d6\u5df2\u5b89\u88c5\u5728\u60a8\u7684\u8bbe\u5907\u4e0a\u7684\u5e94\u7528\u7684\u6709\u5173\u4fe1\u606f",

View File

@ -371,7 +371,7 @@ APK is called F-Droid Privileged Extension.</desc>
<id>info.guardianproject.urzip</id> <id>info.guardianproject.urzip</id>
<added>2016-06-23</added> <added>2016-06-23</added>
<lastupdated>2016-06-23</lastupdated> <lastupdated>2016-06-23</lastupdated>
<name>urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234</name> <name>title</name>
<summary>一个实用工具,获取已安装在您的设备上的应用的有关信息</summary> <summary>一个实用工具,获取已安装在您的设备上的应用的有关信息</summary>
<icon>info.guardianproject.urzip.100.png</icon> <icon>info.guardianproject.urzip.100.png</icon>
<desc>Its Urzip 是一个获得已安装 APK 相关信息的实用工具。它从您的设备上已安装的所有应用开始,一键触摸即可显示 APK 的指纹,并且提供到达 virustotal.com 和 androidobservatory.org 的快捷链接,让您方便地了解特定 APK 的档案。它还可以让您导出签名证书和生成 ApkSignaturePin Pin 文件供 TrustedIntents 库使用。 <desc>Its Urzip 是一个获得已安装 APK 相关信息的实用工具。它从您的设备上已安装的所有应用开始,一键触摸即可显示 APK 的指纹,并且提供到达 virustotal.com 和 androidobservatory.org 的快捷链接,让您方便地了解特定 APK 的档案。它还可以让您导出签名证书和生成 ApkSignaturePin Pin 文件供 TrustedIntents 库使用。

View File

@ -2,6 +2,7 @@
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163 # http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import copy
import git import git
import glob import glob
import inspect import inspect
@ -69,6 +70,10 @@ class UpdateTest(unittest.TestCase):
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logging.getLogger('androguard.axml').setLevel(logging.INFO)
logging.getLogger('androguard.core.api_specific_resources').setLevel(logging.INFO)
from PIL import PngImagePlugin
logging.getLogger(PngImagePlugin.__name__).setLevel(logging.INFO)
self.basedir = os.path.join(localmodule, 'tests') self.basedir = os.path.join(localmodule, 'tests')
self.tmpdir = os.path.abspath(os.path.join(self.basedir, '..', '.testfiles')) self.tmpdir = os.path.abspath(os.path.join(self.basedir, '..', '.testfiles'))
if not os.path.exists(self.tmpdir): if not os.path.exists(self.tmpdir):
@ -174,6 +179,140 @@ class UpdateTest(unittest.TestCase):
elif packageName == 'eu.siacs.conversations': elif packageName == 'eu.siacs.conversations':
self.assertEqual('Conversations', app['localized']['en-US']['name']) self.assertEqual('Conversations', app['localized']['en-US']['name'])
def test_name_title_scraping(self):
"""metadata file --> fdroiddata localized files --> fastlane/triple-t in app source --> APK"""
config = dict()
fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config
fdroidserver.update.config = config
os.chdir(os.path.join(localmodule, 'tests'))
fdroidserver.update.options = type('', (), {})()
fdroidserver.update.options.clean = True
fdroidserver.update.options.delete_unknown = True
fdroidserver.update.options.rename_apks = False
fdroidserver.update.options.allow_disabled_algorithms = False
apps = fdroidserver.metadata.read_metadata()
knownapks = fdroidserver.common.KnownApks()
apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
fdroidserver.update.insert_localized_app_metadata(apps)
fdroidserver.update.apply_info_from_latest_apk(apps, apks)
app = apps['info.guardianproject.urzip']
self.assertIsNone(app.Name)
self.assertTrue('localized' in app)
self.assertEqual('title', app['localized']['en-US']['name'])
app = apps['org.videolan.vlc']
self.assertIsNone(app.Name)
self.assertTrue('localized' in app)
self.assertFalse('name' in app['localized']['en-US'])
app = apps['info.guardianproject.checkey']
self.assertEqual('Checkey the app!', app.Name)
self.assertTrue('localized' in app)
self.assertEqual('Checkey: info on local apps', app['localized']['en-US']['name'])
self.assertEqual('Checkey: ローカルアプリの情報', app['localized']['ja-JP']['name'])
app = apps['org.adaway']
self.assertIsNone(app.Name)
self.assertFalse('localized' in app)
app = apps['obb.main.twoversions']
self.assertIsNone(app.Name)
self.assertFalse('localized' in app)
def test_insert_missing_app_names_from_apks(self):
"""en-US serves as the final, default, fallback value with index-v1"""
testvalue = 'TESTVALUE!'
apps = {
'none': {},
'name': {'Name': testvalue},
'onlyapk': {'Name': None},
'autoname': {'AutoName': 'autoname', 'Name': None},
'onlylocalized': {'localized': {'en-US': {'name': testvalue}}},
'non_en_us_localized': {'localized': {'de-AT': {'name': 'leiwand'}}},
'apks': {},
}
apks = [
{'packageName': 'none', 'name': '', 'versionCode': 1},
{'packageName': 'name', 'name': 'fromapk', 'versionCode': 1},
{'packageName': 'onlyapk', 'name': testvalue, 'versionCode': 1},
{'packageName': 'autoname', 'name': testvalue, 'versionCode': 1},
{'packageName': 'onlylocalized', 'name': 'fromapk', 'versionCode': 1},
{'packageName': 'non_en_us_localized', 'name': testvalue, 'versionCode': 0xcafe},
{'packageName': 'apks', 'name': 'fromapk1', 'versionCode': 1},
{'packageName': 'apks', 'name': 'fromapk2', 'versionCode': 2},
{'packageName': 'apks', 'name': testvalue, 'versionCode': 3},
]
fdroidserver.update.insert_missing_app_names_from_apks(apps, apks)
for appid, app in apps.items():
if appid == 'none':
self.assertIsNone(app.get('Name'))
self.assertIsNone(app.get('localized'))
elif appid == 'onlyapk':
self.assertIsNone(app.get('Name'))
self.assertEqual(testvalue, app['localized']['en-US']['name'])
elif appid == 'autoname':
self.assertIsNone(app.get('Name'))
self.assertEqual(testvalue, app['localized']['en-US']['name'])
elif appid == 'onlylocalized':
self.assertIsNone(app.get('Name'))
self.assertEqual(testvalue, app['localized']['en-US']['name'])
elif appid == 'non_en_us_localized':
self.assertIsNone(app.get('Name'))
self.assertEqual(testvalue, app['localized']['en-US']['name'])
elif appid == 'name':
self.assertEqual(testvalue, app['Name'])
self.assertIsNone(app.get('localized'))
elif appid == 'apks':
self.assertIsNone(app.get('Name'))
self.assertEqual(testvalue, app['localized']['en-US']['name'])
def test_insert_missing_app_names_from_apks_from_repo(self):
config = dict()
fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config
fdroidserver.update.config = config
fdroidserver.update.options = type('', (), {})()
fdroidserver.update.options.clean = True
fdroidserver.update.options.delete_unknown = True
fdroidserver.update.options.rename_apks = False
fdroidserver.update.options.allow_disabled_algorithms = False
apps = fdroidserver.metadata.read_metadata()
knownapks = fdroidserver.common.KnownApks()
apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
appid = 'info.guardianproject.checkey'
testapps = {appid: copy.copy(apps[appid])}
self.assertEqual('Checkey the app!', testapps[appid]['Name'])
del(testapps[appid]['Name'])
fdroidserver.update.insert_missing_app_names_from_apks(testapps, apks)
self.assertIsNone(testapps[appid].get('Name'))
repoapps = fdroidserver.update.prepare_apps(apps, apks, 'repo')
fdroidserver.update.insert_missing_app_names_from_apks(repoapps, apks)
self.assertIsNone(repoapps['com.politedroid']['Name'])
self.assertEqual('Polite Droid',
repoapps['com.politedroid']['localized']['en-US']['name'])
self.assertEqual('Duplicate Permisssions', repoapps['duplicate.permisssions']['Name'])
self.assertEqual('Caffeine Tile', repoapps['info.zwanenburg.caffeinetile']['Name'])
self.assertEqual('No minSdkVersion or targetSdkVersion', repoapps['no.min.target.sdk']['Name'])
self.assertIsNone(repoapps['obb.main.oldversion'].get('Name'))
self.assertEqual('OBB Main Old Version',
repoapps['obb.main.oldversion']['localized']['en-US']['name'])
self.assertIsNone(repoapps['obb.main.twoversions'].get('Name'))
self.assertEqual('OBB Main Two Versions',
repoapps['obb.main.twoversions']['localized']['en-US']['name'])
self.assertIsNone(repoapps['souch.smsbypass'].get('Name'))
self.assertEqual('Battery level',
repoapps['souch.smsbypass']['localized']['en-US']['name'])
self.assertIsNone(repoapps['info.guardianproject.urzip'].get('Name'))
self.assertEqual('title',
repoapps['info.guardianproject.urzip']['localized']['en-US']['name'])
self.assertIsNone(repoapps['obb.mainpatch.current'].get('Name'))
del(repoapps['info.guardianproject.urzip']['localized'])
fdroidserver.update.insert_missing_app_names_from_apks(repoapps, apks)
self.assertEqual('urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234',
repoapps['info.guardianproject.urzip']['localized']['en-US']['name'])
def test_insert_triple_t_metadata(self): def test_insert_triple_t_metadata(self):
importer = os.path.join(self.basedir, 'tmp', 'importer') importer = os.path.join(self.basedir, 'tmp', 'importer')
packageName = 'org.fdroid.ci.test.app' packageName = 'org.fdroid.ci.test.app'