diff --git a/fdroidserver/index.py b/fdroidserver/index.py index 63d41962..860abcf6 100644 --- a/fdroidserver/index.py +++ b/fdroidserver/index.py @@ -643,13 +643,6 @@ def convert_version(version, app, repodir): if "versionCode" in version: manifest["versionCode"] = version["versionCode"] - if "features" in version and version["features"]: - manifest["features"] = features = [] - for feature in version["features"]: - # TODO get version from manifest, default (0) is omitted - # features.append({"name": feature, "version": 1}) - features.append({"name": feature}) - if "minSdkVersion" in version: manifest["usesSdk"] = {} manifest["usesSdk"]["minSdkVersion"] = version["minSdkVersion"] @@ -906,6 +899,16 @@ def make_v2( signindex.sign_index(repodir, json_name) +def _get_sorted_name_list_from_dict(l_of_d): + """Return a sorted list of strings from a index-v2 list of dicts.""" + if not l_of_d: + return list() + name_list = list() + for d in l_of_d: + name_list.append(d['name']) + return sorted(name_list) + + def make_v1(apps, packages, repodir, repodict, requestsdict, signer_fingerprints): def _index_encoder_default(obj): if isinstance(obj, set): @@ -1052,7 +1055,9 @@ def make_v1(apps, packages, repodir, repodict, requestsdict, signer_fingerprints if not mv: continue - if mk == 'usesPermission': + if mk == 'features': + d[mk] = _get_sorted_name_list_from_dict(mv) + elif mk == 'usesPermission': up_list = list() for p in mv: up_list.append((p['name'], p.get('maxSdkVersion'))) @@ -1417,7 +1422,12 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, signer_fingerprints): doc, apkel, ) - addElementNonEmpty('features', ','.join(sorted(apk['features'])), doc, apkel) # fmt: skip + addElementNonEmpty( + 'features', + ','.join(_get_sorted_name_list_from_dict(manifest.get('features'))), + doc, + apkel, + ) if ( current_version_file is not None diff --git a/fdroidserver/update.py b/fdroidserver/update.py index fadd953e..09a90d43 100644 --- a/fdroidserver/update.py +++ b/fdroidserver/update.py @@ -1671,7 +1671,6 @@ def scan_apk(apk_file, require_signature=True): apk = { 'hash': common.sha256sum(apk_file), 'hashType': 'sha256', - 'features': [], 'icons_src': {}, 'icons': {}, 'antiFeatures': {}, @@ -1982,10 +1981,12 @@ def scan_apk_androguard(apk, apkfile): 'android.hardware.screen.landscape', ): if feature.startswith("android.feature."): - feature = feature[16:] + feature = feature[16:] # TODO delete this madness in index-v3 required = item.attrib.get(xmlns + 'required') if required is None or required == 'true': - apk['features'].append(feature) + if 'features' not in apk: + manifest['features'] = list() + manifest['features'].append({'name': feature}) _DISABLED_ALGORITHM_REASON = None diff --git a/tests/metadata/apk/info.guardianproject.urzip.yaml b/tests/metadata/apk/info.guardianproject.urzip.yaml index 22ec4e83..33d7ad0e 100644 --- a/tests/metadata/apk/info.guardianproject.urzip.yaml +++ b/tests/metadata/apk/info.guardianproject.urzip.yaml @@ -1,5 +1,4 @@ antiFeatures: {} -features: [] hash: abfb3adb7496611749e7abfb014c5c789e3a02489e48a5c3665110d1b1acd931 hashType: sha256 icon: info.guardianproject.urzip.100.png diff --git a/tests/metadata/apk/org.dyndns.fules.ck.yaml b/tests/metadata/apk/org.dyndns.fules.ck.yaml index 897204a5..fcd7914e 100644 --- a/tests/metadata/apk/org.dyndns.fules.ck.yaml +++ b/tests/metadata/apk/org.dyndns.fules.ck.yaml @@ -1,5 +1,4 @@ antiFeatures: {} -features: [] hash: 897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8 hashType: sha256 icon: org.dyndns.fules.ck.20.png diff --git a/tests/test_index.py b/tests/test_index.py index 4b2a5013..4711b87d 100755 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -875,6 +875,26 @@ class IndexTest(unittest.TestCase): with self.assertRaises(fdroidserver.exception.FDroidException): index.add_mirrors_to_repodict('repo', repodict) + def test_get_sorted_name_list_from_dict(self): + self.assertEqual( + ['bar', 'foo'], + fdroidserver.index._get_sorted_name_list_from_dict( + [{'name': 'foo'}, {'name': 'bar', 'max': 123}] + ), + ) + + def test_get_sorted_name_list_from_dict_none(self): + self.assertEqual( + [], + fdroidserver.index._get_sorted_name_list_from_dict(None), + ) + + def test_get_sorted_name_list_from_dict_empty(self): + self.assertEqual( + [], + fdroidserver.index._get_sorted_name_list_from_dict(list()), + ) + class AltstoreIndexTest(unittest.TestCase): def test_make_altstore(self): diff --git a/tests/test_update.py b/tests/test_update.py index 6fc5d8ce..5be8db2b 100755 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -904,8 +904,8 @@ class UpdateTest(unittest.TestCase): self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_launcher.png', '-1': 'res/drawable/ic_launcher.png'}) self.assertEqual( - apk_info['features'], - ['android.hardware.telephony'], + apk_info['manifest']['features'], + [{'name': 'android.hardware.telephony'}], ) def test_scan_apk_lots_of_data(self): @@ -915,7 +915,6 @@ class UpdateTest(unittest.TestCase): '160': 'res/drawable-mdpi-v4/icon_launcher.png', '-1': 'res/drawable-mdpi-v4/icon_launcher.png'}) self.assertEqual(apk_info['icons'], {}) - self.assertEqual(apk_info['features'], []) self.assertEqual(apk_info['antiFeatures'], dict()) self.assertEqual(apk_info['versionName'], 'v1.6pre2') self.assertEqual(apk_info['hash'], @@ -979,7 +978,6 @@ class UpdateTest(unittest.TestCase): 'signer': '32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6', 'hashType': 'sha256', 'packageName': 'no.min.target.sdk', - 'features': [], 'antiFeatures': dict(), 'size': 14102, 'sig': 'b4964fd759edaa54e65bb476d0276880', @@ -1892,7 +1890,6 @@ class UpdateTest(unittest.TestCase): """Create an empty apk metadata object.""" apk = {} apk['apkName'] = apkName - apk['features'] = [] apk['icons_src'] = {} return apk @@ -1901,7 +1898,6 @@ class UpdateTest(unittest.TestCase): 'org.dyndns.fules.ck_20.apk', { 'apkName': 'org.dyndns.fules.ck_20.apk', - 'features': [], 'icons_src': { '240': 'res/drawable-hdpi-v4/icon_launcher.png', '120': 'res/drawable-ldpi-v4/icon_launcher.png',