mirror of
https://github.com/f-droid/fdroidserver.git
synced 2025-11-10 01:00:29 +03:00
Merge branch 'indexing-fixes' into 'master'
indexing fixes Closes #303 See merge request !270
This commit is contained in:
commit
780b0e9502
10 changed files with 42 additions and 30 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -39,5 +39,6 @@ makebuildserver.config.py
|
||||||
/tests/archive/index-v1.jar
|
/tests/archive/index-v1.jar
|
||||||
/tests/repo/index.jar
|
/tests/repo/index.jar
|
||||||
/tests/repo/index-v1.jar
|
/tests/repo/index-v1.jar
|
||||||
|
/tests/repo/info.guardianproject.urzip/
|
||||||
/tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk
|
/tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk
|
||||||
/unsigned/
|
/unsigned/
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@ def get_apk_metadata_androguard(apkfile):
|
||||||
def get_metadata_from_apk(app, build, apkfile):
|
def get_metadata_from_apk(app, build, apkfile):
|
||||||
"""get the required metadata from the built APK"""
|
"""get the required metadata from the built APK"""
|
||||||
|
|
||||||
if common.set_command_in_config('aapt'):
|
if common.SdkToolsPopen(['aapt', 'version'], output=False):
|
||||||
vercode, version, foundid, nativecode = get_apk_metadata_aapt(apkfile)
|
vercode, version, foundid, nativecode = get_apk_metadata_aapt(apkfile)
|
||||||
else:
|
else:
|
||||||
vercode, version, foundid, nativecode = get_apk_metadata_androguard(apkfile)
|
vercode, version, foundid, nativecode = get_apk_metadata_androguard(apkfile)
|
||||||
|
|
|
||||||
|
|
@ -1727,7 +1727,7 @@ def isApkAndDebuggable(apkfile, config):
|
||||||
if get_file_extension(apkfile) != 'apk':
|
if get_file_extension(apkfile) != 'apk':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if set_command_in_config('aapt'):
|
if SdkToolsPopen(['aapt', 'version'], output=False):
|
||||||
return get_apk_debuggable_aapt(apkfile)
|
return get_apk_debuggable_aapt(apkfile)
|
||||||
else:
|
else:
|
||||||
return get_apk_debuggable_androguard(apkfile)
|
return get_apk_debuggable_androguard(apkfile)
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict):
|
||||||
|
|
||||||
appslist = []
|
appslist = []
|
||||||
output['apps'] = appslist
|
output['apps'] = appslist
|
||||||
for appid, appdict in apps.items():
|
for packageName, appdict in apps.items():
|
||||||
d = collections.OrderedDict()
|
d = collections.OrderedDict()
|
||||||
appslist.append(d)
|
appslist.append(d)
|
||||||
for k, v in sorted(appdict.items()):
|
for k, v in sorted(appdict.items()):
|
||||||
|
|
@ -190,7 +190,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict):
|
||||||
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':
|
elif k == 'AutoName':
|
||||||
if 'Name' not in apps[appid]:
|
if 'Name' not in apps[packageName]:
|
||||||
d['name'] = v
|
d['name'] = v
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
|
@ -201,6 +201,9 @@ def make_v1(apps, packages, repodir, repodict, requestsdict):
|
||||||
output['packages'] = output_packages
|
output['packages'] = output_packages
|
||||||
for package in packages:
|
for package in packages:
|
||||||
packageName = package['packageName']
|
packageName = package['packageName']
|
||||||
|
if packageName not in apps:
|
||||||
|
logging.info('Ignoring package without metadata: ' + package['apkName'])
|
||||||
|
continue
|
||||||
if packageName in output_packages:
|
if packageName in output_packages:
|
||||||
packagelist = output_packages[packageName]
|
packagelist = output_packages[packageName]
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import glob
|
import glob
|
||||||
import cgi
|
import html
|
||||||
import logging
|
import logging
|
||||||
import textwrap
|
import textwrap
|
||||||
import io
|
import io
|
||||||
|
|
@ -492,10 +492,10 @@ class DescriptionFormatter:
|
||||||
self.laststate = self.state
|
self.laststate = self.state
|
||||||
self.state = self.stNONE
|
self.state = self.stNONE
|
||||||
|
|
||||||
def formatted(self, txt, html):
|
def formatted(self, txt, htmlbody):
|
||||||
res = ''
|
res = ''
|
||||||
if html:
|
if htmlbody:
|
||||||
txt = cgi.escape(txt)
|
txt = html.escape(txt, quote=False)
|
||||||
while True:
|
while True:
|
||||||
index = txt.find("''")
|
index = txt.find("''")
|
||||||
if index == -1:
|
if index == -1:
|
||||||
|
|
@ -503,7 +503,7 @@ class DescriptionFormatter:
|
||||||
res += txt[:index]
|
res += txt[:index]
|
||||||
txt = txt[index:]
|
txt = txt[index:]
|
||||||
if txt.startswith("'''"):
|
if txt.startswith("'''"):
|
||||||
if html:
|
if htmlbody:
|
||||||
if self.bold:
|
if self.bold:
|
||||||
res += '</b>'
|
res += '</b>'
|
||||||
else:
|
else:
|
||||||
|
|
@ -511,7 +511,7 @@ class DescriptionFormatter:
|
||||||
self.bold = not self.bold
|
self.bold = not self.bold
|
||||||
txt = txt[3:]
|
txt = txt[3:]
|
||||||
else:
|
else:
|
||||||
if html:
|
if htmlbody:
|
||||||
if self.ital:
|
if self.ital:
|
||||||
res += '</i>'
|
res += '</i>'
|
||||||
else:
|
else:
|
||||||
|
|
@ -538,7 +538,7 @@ class DescriptionFormatter:
|
||||||
url, urltext = self.linkResolver(url)
|
url, urltext = self.linkResolver(url)
|
||||||
else:
|
else:
|
||||||
urltext = url
|
urltext = url
|
||||||
res_html += '<a href="' + url + '">' + cgi.escape(urltext) + '</a>'
|
res_html += '<a href="' + url + '">' + html.escape(urltext, quote=False) + '</a>'
|
||||||
res_plain += urltext
|
res_plain += urltext
|
||||||
txt = txt[index + 2:]
|
txt = txt[index + 2:]
|
||||||
else:
|
else:
|
||||||
|
|
@ -554,7 +554,7 @@ class DescriptionFormatter:
|
||||||
url = url[:index2]
|
url = url[:index2]
|
||||||
if url == urltxt:
|
if url == urltxt:
|
||||||
warn_or_exception("Url title is just the URL - use [url]")
|
warn_or_exception("Url title is just the URL - use [url]")
|
||||||
res_html += '<a href="' + url + '">' + cgi.escape(urltxt) + '</a>'
|
res_html += '<a href="' + url + '">' + html.escape(urltxt, quote=False) + '</a>'
|
||||||
res_plain += urltxt
|
res_plain += urltxt
|
||||||
if urltxt != url:
|
if urltxt != url:
|
||||||
res_plain += ' (' + url + ')'
|
res_plain += ' (' + url + ')'
|
||||||
|
|
|
||||||
|
|
@ -676,14 +676,14 @@ def insert_localized_app_metadata(apps):
|
||||||
must be PNG or JPEG files ending with ".png", ".jpg", or ".jpeg"
|
must be PNG or JPEG files ending with ".png", ".jpg", or ".jpeg"
|
||||||
and must be in the following layout:
|
and must be in the following layout:
|
||||||
# TODO replace these docs with link to All_About_Descriptions_Graphics_and_Screenshots
|
# TODO replace these docs with link to All_About_Descriptions_Graphics_and_Screenshots
|
||||||
# TODO mention that the 'localized' section is not in metadata.yml, so key names are like Java vars: camelCase with first letter lowercase.
|
|
||||||
repo/packageName/locale/featureGraphic.png
|
repo/packageName/locale/featureGraphic.png
|
||||||
repo/packageName/locale/phoneScreenshots/1.png
|
repo/packageName/locale/phoneScreenshots/1.png
|
||||||
repo/packageName/locale/phoneScreenshots/2.png
|
repo/packageName/locale/phoneScreenshots/2.png
|
||||||
|
|
||||||
The changelog files must be text files named with the versionCode
|
The changelog files must be text files named with the versionCode
|
||||||
ending with ".txt" and must be in the following layout:
|
ending with ".txt" and must be in the following layout:
|
||||||
https://github.com/fastlane/fastlane/blob/1.109.0/supply/README.md#changelogs-whats-new
|
https://github.com/fastlane/fastlane/blob/2.28.7/supply/README.md#changelogs-whats-new
|
||||||
|
|
||||||
repo/packageName/locale/changelogs/12345.txt
|
repo/packageName/locale/changelogs/12345.txt
|
||||||
|
|
||||||
|
|
@ -701,7 +701,7 @@ def insert_localized_app_metadata(apps):
|
||||||
metadata/ folder and the apps' source repos for standard locations
|
metadata/ folder and the apps' source repos for standard locations
|
||||||
of graphic and screenshot files. If it finds them, it will copy
|
of graphic and screenshot files. If it finds them, it will copy
|
||||||
them into the repo. The fastlane files follow this pattern:
|
them into the repo. The fastlane files follow this pattern:
|
||||||
https://github.com/fastlane/fastlane/blob/1.109.0/supply/README.md#images-and-screenshots
|
https://github.com/fastlane/fastlane/blob/2.28.7/supply/README.md#images-and-screenshots
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -718,7 +718,6 @@ def insert_localized_app_metadata(apps):
|
||||||
logging.debug(packageName + ' does not have app metadata, skipping l18n scan.')
|
logging.debug(packageName + ' does not have app metadata, skipping l18n scan.')
|
||||||
continue
|
continue
|
||||||
locale = segments[-1]
|
locale = segments[-1]
|
||||||
destdir = os.path.join('repo', packageName, locale)
|
|
||||||
for f in files:
|
for f in files:
|
||||||
if f == 'full_description.txt':
|
if f == 'full_description.txt':
|
||||||
_set_localized_text_entry(apps[packageName], locale, 'description',
|
_set_localized_text_entry(apps[packageName], locale, 'description',
|
||||||
|
|
@ -737,11 +736,15 @@ def insert_localized_app_metadata(apps):
|
||||||
os.path.join(root, f))
|
os.path.join(root, f))
|
||||||
continue
|
continue
|
||||||
elif f == str(apps[packageName]['CurrentVersionCode']) + '.txt':
|
elif f == str(apps[packageName]['CurrentVersionCode']) + '.txt':
|
||||||
_set_localized_text_entry(apps[packageName], segments[-2], 'whatsNew',
|
locale = segments[-2]
|
||||||
|
_set_localized_text_entry(apps[packageName], locale, 'whatsNew',
|
||||||
os.path.join(root, f))
|
os.path.join(root, f))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
base, extension = common.get_extension(f)
|
base, extension = common.get_extension(f)
|
||||||
|
if locale == 'images':
|
||||||
|
locale = segments[-2]
|
||||||
|
destdir = os.path.join('repo', packageName, locale)
|
||||||
if base in GRAPHIC_NAMES and extension in ALLOWED_EXTENSIONS:
|
if base in GRAPHIC_NAMES and extension in ALLOWED_EXTENSIONS:
|
||||||
os.makedirs(destdir, mode=0o755, exist_ok=True)
|
os.makedirs(destdir, mode=0o755, exist_ok=True)
|
||||||
logging.debug('copying ' + os.path.join(root, f) + ' ' + destdir)
|
logging.debug('copying ' + os.path.join(root, f) + ' ' + destdir)
|
||||||
|
|
@ -783,7 +786,7 @@ def insert_localized_app_metadata(apps):
|
||||||
graphics[base] = filename
|
graphics[base] = filename
|
||||||
elif screenshotdir in SCREENSHOT_DIRS:
|
elif screenshotdir in SCREENSHOT_DIRS:
|
||||||
# there can any number of these per locale
|
# there can any number of these per locale
|
||||||
logging.debug('adding ' + base + ':' + f)
|
logging.debug('adding to ' + screenshotdir + ': ' + f)
|
||||||
if screenshotdir not in graphics:
|
if screenshotdir not in graphics:
|
||||||
graphics[screenshotdir] = []
|
graphics[screenshotdir] = []
|
||||||
graphics[screenshotdir].append(filename)
|
graphics[screenshotdir].append(filename)
|
||||||
|
|
@ -849,12 +852,13 @@ def scan_repo_files(apkcache, repodir, knownapks, use_date_from_file=False):
|
||||||
repo_file['versionName'] = shasum
|
repo_file['versionName'] = shasum
|
||||||
# the static ID is the SHA256 unless it is set in the metadata
|
# the static ID is the SHA256 unless it is set in the metadata
|
||||||
repo_file['packageName'] = shasum
|
repo_file['packageName'] = shasum
|
||||||
n = name_utf8.split('_')
|
|
||||||
|
n = name_utf8.rsplit('_', maxsplit=1)
|
||||||
if len(n) == 2:
|
if len(n) == 2:
|
||||||
packageName = n[0]
|
packageName = n[0]
|
||||||
versionCode = n[1].split('.')[0]
|
versionCode = n[1].split('.')[0]
|
||||||
if re.match('^-?[0-9]+$', versionCode) \
|
if re.match('^-?[0-9]+$', versionCode) \
|
||||||
and common.is_valid_package_name(name_utf8.split('_')[0]):
|
and common.is_valid_package_name(n[0]):
|
||||||
repo_file['packageName'] = packageName
|
repo_file['packageName'] = packageName
|
||||||
repo_file['versionCode'] = int(versionCode)
|
repo_file['versionCode'] = int(versionCode)
|
||||||
srcfilename = name + b'_src.tar.gz'
|
srcfilename = name + b'_src.tar.gz'
|
||||||
|
|
@ -1124,11 +1128,9 @@ def scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk):
|
||||||
apk['antiFeatures'].add('KnownVuln')
|
apk['antiFeatures'].add('KnownVuln')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if common.set_command_in_config('aapt'):
|
if SdkToolsPopen(['aapt', 'version'], output=False):
|
||||||
logging.warning("Using AAPT for metadata")
|
|
||||||
scan_apk_aapt(apk, apkfile)
|
scan_apk_aapt(apk, apkfile)
|
||||||
else:
|
else:
|
||||||
logging.warning("Using androguard for metadata")
|
|
||||||
scan_apk_androguard(apk, apkfile)
|
scan_apk_androguard(apk, apkfile)
|
||||||
except BuildException:
|
except BuildException:
|
||||||
return True, None, False
|
return True, None, False
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,8 @@ import inspect
|
||||||
import logging
|
import logging
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
|
||||||
import unittest
|
import unittest
|
||||||
import yaml
|
|
||||||
from binascii import unhexlify
|
|
||||||
|
|
||||||
localmodule = os.path.realpath(
|
localmodule = os.path.realpath(
|
||||||
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..'))
|
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..'))
|
||||||
|
|
@ -53,9 +49,10 @@ class UpdateTest(unittest.TestCase):
|
||||||
fdroidserver.update.options.clean = True
|
fdroidserver.update.options.clean = True
|
||||||
fdroidserver.update.options.delete_unknown = True
|
fdroidserver.update.options.delete_unknown = True
|
||||||
|
|
||||||
self.assertTrue(fdroidserver.common.set_command_in_config('aapt'))
|
self.assertTrue(fdroidserver.common.SdkToolsPopen('aapt'))
|
||||||
try:
|
try:
|
||||||
from androguard.core.bytecodes.apk import APK
|
from androguard.core.bytecodes.apk import APK
|
||||||
|
dir(APK)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise Exception("androguard not installed!")
|
raise Exception("androguard not installed!")
|
||||||
|
|
||||||
|
|
@ -89,4 +86,4 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(UpdateTest))
|
newSuite.addTest(unittest.makeSuite(UpdateTest))
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
tests/metadata/info.guardianproject.urzip/en-US/images/icon.png
Normal file
BIN
tests/metadata/info.guardianproject.urzip/en-US/images/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -37,6 +37,8 @@ class UpdateTest(unittest.TestCase):
|
||||||
fdroidserver.update.options = fdroidserver.common.options
|
fdroidserver.update.options = fdroidserver.common.options
|
||||||
os.chdir(os.path.join(localmodule, 'tests'))
|
os.chdir(os.path.join(localmodule, 'tests'))
|
||||||
|
|
||||||
|
shutil.rmtree(os.path.join('repo', 'info.guardianproject.urzip'), ignore_errors=True)
|
||||||
|
|
||||||
apps = dict()
|
apps = dict()
|
||||||
for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current'):
|
for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current'):
|
||||||
apps[packageName] = dict()
|
apps[packageName] = dict()
|
||||||
|
|
@ -45,17 +47,23 @@ class UpdateTest(unittest.TestCase):
|
||||||
apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
|
apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
|
||||||
fdroidserver.update.insert_localized_app_metadata(apps)
|
fdroidserver.update.insert_localized_app_metadata(apps)
|
||||||
|
|
||||||
|
appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US')
|
||||||
|
self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png')))
|
||||||
|
self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png')))
|
||||||
|
|
||||||
self.assertEqual(3, len(apps))
|
self.assertEqual(3, len(apps))
|
||||||
for packageName, app in apps.items():
|
for packageName, app in apps.items():
|
||||||
self.assertTrue('localized' in app)
|
self.assertTrue('localized' in app)
|
||||||
self.assertTrue('en-US' in app['localized'])
|
self.assertTrue('en-US' in app['localized'])
|
||||||
self.assertEqual(1, len(app['localized']))
|
self.assertEqual(1, len(app['localized']))
|
||||||
if packageName == 'info.guardianproject.urzip':
|
if packageName == 'info.guardianproject.urzip':
|
||||||
self.assertEqual(5, len(app['localized']['en-US']))
|
self.assertEqual(7, len(app['localized']['en-US']))
|
||||||
self.assertEqual('full description\n', app['localized']['en-US']['description'])
|
self.assertEqual('full description\n', app['localized']['en-US']['description'])
|
||||||
self.assertEqual('title\n', app['localized']['en-US']['name'])
|
self.assertEqual('title\n', app['localized']['en-US']['name'])
|
||||||
self.assertEqual('short description\n', app['localized']['en-US']['summary'])
|
self.assertEqual('short description\n', app['localized']['en-US']['summary'])
|
||||||
self.assertEqual('video\n', app['localized']['en-US']['video'])
|
self.assertEqual('video\n', app['localized']['en-US']['video'])
|
||||||
|
self.assertEqual('icon.png', app['localized']['en-US']['icon'])
|
||||||
|
self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
|
||||||
self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
|
self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
|
||||||
elif packageName == 'org.videolan.vlc':
|
elif packageName == 'org.videolan.vlc':
|
||||||
self.assertEqual('icon.png', app['localized']['en-US']['icon'])
|
self.assertEqual('icon.png', app['localized']['en-US']['icon'])
|
||||||
|
|
@ -244,6 +252,7 @@ class UpdateTest(unittest.TestCase):
|
||||||
|
|
||||||
fdroidserver.update.options = type('', (), {})()
|
fdroidserver.update.options = type('', (), {})()
|
||||||
fdroidserver.update.options.clean = True
|
fdroidserver.update.options.clean = True
|
||||||
|
fdroidserver.update.options.rename_apks = False
|
||||||
fdroidserver.update.options.delete_unknown = True
|
fdroidserver.update.options.delete_unknown = True
|
||||||
|
|
||||||
for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
|
for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue