mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-10-06 11:00:13 +02:00
Merge branch 'more-1.0-polishing' into 'master'
More 1.0 polishing Closes #402 See merge request fdroid/fdroidserver!362
This commit is contained in:
commit
e666cd9b35
19
.travis.yml
19
.travis.yml
@ -19,6 +19,9 @@ matrix:
|
|||||||
env: ANDROID_SDK_ROOT=/usr/local/share/android-sdk
|
env: ANDROID_SDK_ROOT=/usr/local/share/android-sdk
|
||||||
env: ANDROID_HOME=/usr/local/share/android-sdk
|
env: ANDROID_HOME=/usr/local/share/android-sdk
|
||||||
|
|
||||||
|
# On Ubuntu/trusty 14.04, the PPA is needed on to provide lots of the
|
||||||
|
# dependencies, but this then also serves as a test of the PPA, which
|
||||||
|
# is used on Windows Subsystem for Linux.
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@ -46,15 +49,13 @@ android:
|
|||||||
- 'android-sdk-preview-.+'
|
- 'android-sdk-preview-.+'
|
||||||
- 'android-sdk-license-.+'
|
- 'android-sdk-license-.+'
|
||||||
|
|
||||||
# the PPA is needed on Ubuntu 14.04 precise, and with python3, trusty too
|
|
||||||
# the pip thing is a hack that can go away with trusty.
|
|
||||||
#
|
|
||||||
# * ensure java8 is installed since Android SDK doesn't work with Java9
|
# * ensure java8 is installed since Android SDK doesn't work with Java9
|
||||||
# * Java needs to be at least 1.8.0_131 to have MD5 properly disabled
|
# * Java needs to be at least 1.8.0_131 to have MD5 properly disabled
|
||||||
# https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
|
# https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
|
||||||
# https://opsech.io/posts/2017/Jun/09/openjdk-april-2017-security-update-131-8u131-and-md5-signed-jars.html
|
# https://opsech.io/posts/2017/Jun/09/openjdk-april-2017-security-update-131-8u131-and-md5-signed-jars.html
|
||||||
install:
|
install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
|
set -x;
|
||||||
brew update > /dev/null;
|
brew update > /dev/null;
|
||||||
brew install dash bash python3 gradle jenv;
|
brew install dash bash python3 gradle jenv;
|
||||||
brew install gnu-sed --with-default-names;
|
brew install gnu-sed --with-default-names;
|
||||||
@ -74,6 +75,8 @@ install:
|
|||||||
sudo pip3 install --quiet --editable . ;
|
sudo pip3 install --quiet --editable . ;
|
||||||
sudo rm -rf fdroidserver.egg-info;
|
sudo rm -rf fdroidserver.egg-info;
|
||||||
|
|
||||||
|
ls -l /System/Library/Java/JavaVirtualMachines || true;
|
||||||
|
ls -l /Library/Java/JavaVirtualMachines || true;
|
||||||
echo $PATH;
|
echo $PATH;
|
||||||
echo $JAVA_HOME;
|
echo $JAVA_HOME;
|
||||||
jenv versions;
|
jenv versions;
|
||||||
@ -86,11 +89,19 @@ install:
|
|||||||
which jarsigner;
|
which jarsigner;
|
||||||
keytool -help;
|
keytool -help;
|
||||||
which keytool;
|
which keytool;
|
||||||
|
set +x;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# The OSX tests seem to run slower, they often timeout. So only run
|
||||||
|
# the test suite with the installed version of fdroid, instead of the
|
||||||
|
# three rounds that ./complete-ci-tests does.
|
||||||
script:
|
script:
|
||||||
- cd tests
|
- cd tests
|
||||||
- ./complete-ci-tests
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
|
./run-tests;
|
||||||
|
else
|
||||||
|
./complete-ci-tests;
|
||||||
|
fi
|
||||||
|
|
||||||
after_failure:
|
after_failure:
|
||||||
- cd $TRAVIS_BUILD_DIR
|
- cd $TRAVIS_BUILD_DIR
|
||||||
|
@ -132,6 +132,41 @@ def setup_global_opts(parser):
|
|||||||
help=_("Restrict output to warnings and errors"))
|
help=_("Restrict output to warnings and errors"))
|
||||||
|
|
||||||
|
|
||||||
|
def _add_java_paths_to_config(pathlist, thisconfig):
|
||||||
|
def path_version_key(s):
|
||||||
|
versionlist = []
|
||||||
|
for u in re.split('[^0-9]+', s):
|
||||||
|
try:
|
||||||
|
versionlist.append(int(u))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return versionlist
|
||||||
|
|
||||||
|
for d in sorted(pathlist, key=path_version_key):
|
||||||
|
if os.path.islink(d):
|
||||||
|
continue
|
||||||
|
j = os.path.basename(d)
|
||||||
|
# the last one found will be the canonical one, so order appropriately
|
||||||
|
for regex in [
|
||||||
|
r'^1\.([6-9])\.0\.jdk$', # OSX
|
||||||
|
r'^jdk1\.([6-9])\.0_[0-9]+.jdk$', # OSX and Oracle tarball
|
||||||
|
r'^jdk1\.([6-9])\.0_[0-9]+$', # Oracle Windows
|
||||||
|
r'^jdk([6-9])-openjdk$', # Arch
|
||||||
|
r'^java-([6-9])-openjdk$', # Arch
|
||||||
|
r'^java-([6-9])-jdk$', # Arch (oracle)
|
||||||
|
r'^java-1\.([6-9])\.0-.*$', # RedHat
|
||||||
|
r'^java-([6-9])-oracle$', # Debian WebUpd8
|
||||||
|
r'^jdk-([6-9])-oracle-.*$', # Debian make-jpkg
|
||||||
|
r'^java-([6-9])-openjdk-[^c][^o][^m].*$', # Debian
|
||||||
|
]:
|
||||||
|
m = re.match(regex, j)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
for p in [d, os.path.join(d, 'Contents', 'Home')]:
|
||||||
|
if os.path.exists(os.path.join(p, 'bin', 'javac')):
|
||||||
|
thisconfig['java_paths'][m.group(1)] = p
|
||||||
|
|
||||||
|
|
||||||
def fill_config_defaults(thisconfig):
|
def fill_config_defaults(thisconfig):
|
||||||
for k, v in default_config.items():
|
for k, v in default_config.items():
|
||||||
if k not in thisconfig:
|
if k not in thisconfig:
|
||||||
@ -167,29 +202,7 @@ def fill_config_defaults(thisconfig):
|
|||||||
pathlist.append(os.getenv('JAVA_HOME'))
|
pathlist.append(os.getenv('JAVA_HOME'))
|
||||||
if os.getenv('PROGRAMFILES') is not None:
|
if os.getenv('PROGRAMFILES') is not None:
|
||||||
pathlist += glob.glob(os.path.join(os.getenv('PROGRAMFILES'), 'Java', 'jdk1.[6-9].*'))
|
pathlist += glob.glob(os.path.join(os.getenv('PROGRAMFILES'), 'Java', 'jdk1.[6-9].*'))
|
||||||
for d in sorted(pathlist):
|
_add_java_paths_to_config(pathlist, thisconfig)
|
||||||
if os.path.islink(d):
|
|
||||||
continue
|
|
||||||
j = os.path.basename(d)
|
|
||||||
# the last one found will be the canonical one, so order appropriately
|
|
||||||
for regex in [
|
|
||||||
r'^1\.([6-9])\.0\.jdk$', # OSX
|
|
||||||
r'^jdk1\.([6-9])\.0_[0-9]+.jdk$', # OSX and Oracle tarball
|
|
||||||
r'^jdk1\.([6-9])\.0_[0-9]+$', # Oracle Windows
|
|
||||||
r'^jdk([6-9])-openjdk$', # Arch
|
|
||||||
r'^java-([6-9])-openjdk$', # Arch
|
|
||||||
r'^java-([6-9])-jdk$', # Arch (oracle)
|
|
||||||
r'^java-1\.([6-9])\.0-.*$', # RedHat
|
|
||||||
r'^java-([6-9])-oracle$', # Debian WebUpd8
|
|
||||||
r'^jdk-([6-9])-oracle-.*$', # Debian make-jpkg
|
|
||||||
r'^java-([6-9])-openjdk-[^c][^o][^m].*$', # Debian
|
|
||||||
]:
|
|
||||||
m = re.match(regex, j)
|
|
||||||
if not m:
|
|
||||||
continue
|
|
||||||
for p in [d, os.path.join(d, 'Contents', 'Home')]:
|
|
||||||
if os.path.exists(os.path.join(p, 'bin', 'javac')):
|
|
||||||
thisconfig['java_paths'][m.group(1)] = p
|
|
||||||
|
|
||||||
for java_version in ('7', '8', '9'):
|
for java_version in ('7', '8', '9'):
|
||||||
if java_version not in thisconfig['java_paths']:
|
if java_version not in thisconfig['java_paths']:
|
||||||
@ -506,7 +519,7 @@ def get_extension(filename):
|
|||||||
|
|
||||||
|
|
||||||
def has_extension(filename, ext):
|
def has_extension(filename, ext):
|
||||||
_, f_ext = get_extension(filename)
|
_ignored, f_ext = get_extension(filename)
|
||||||
return ext == f_ext
|
return ext == f_ext
|
||||||
|
|
||||||
|
|
||||||
@ -1732,7 +1745,7 @@ class KnownApks:
|
|||||||
default_date = datetime.utcnow()
|
default_date = datetime.utcnow()
|
||||||
self.apks[apkName] = (app, default_date)
|
self.apks[apkName] = (app, default_date)
|
||||||
self.changed = True
|
self.changed = True
|
||||||
_, added = self.apks[apkName]
|
_ignored, added = self.apks[apkName]
|
||||||
return added
|
return added
|
||||||
|
|
||||||
def getapp(self, apkname):
|
def getapp(self, apkname):
|
||||||
@ -2238,15 +2251,15 @@ def apk_strip_signatures(signed_apk, strip_manifest=False):
|
|||||||
os.rename(signed_apk, tmp_apk)
|
os.rename(signed_apk, tmp_apk)
|
||||||
with ZipFile(tmp_apk, 'r') as in_apk:
|
with ZipFile(tmp_apk, 'r') as in_apk:
|
||||||
with ZipFile(signed_apk, 'w') as out_apk:
|
with ZipFile(signed_apk, 'w') as out_apk:
|
||||||
for f in in_apk.infolist():
|
for info in in_apk.infolist():
|
||||||
if not apk_sigfile.match(f.filename):
|
if not apk_sigfile.match(info.filename):
|
||||||
if strip_manifest:
|
if strip_manifest:
|
||||||
if f.filename != 'META-INF/MANIFEST.MF':
|
if info.filename != 'META-INF/MANIFEST.MF':
|
||||||
buf = in_apk.read(f.filename)
|
buf = in_apk.read(info.filename)
|
||||||
out_apk.writestr(f.filename, buf)
|
out_apk.writestr(info, buf)
|
||||||
else:
|
else:
|
||||||
buf = in_apk.read(f.filename)
|
buf = in_apk.read(info.filename)
|
||||||
out_apk.writestr(f.filename, buf)
|
out_apk.writestr(info, buf)
|
||||||
|
|
||||||
|
|
||||||
def apk_implant_signatures(apkpath, signaturefile, signedfile, manifest):
|
def apk_implant_signatures(apkpath, signaturefile, signedfile, manifest):
|
||||||
@ -2259,19 +2272,21 @@ def apk_implant_signatures(apkpath, signaturefile, signedfile, manifest):
|
|||||||
"""
|
"""
|
||||||
# get list of available signature files in metadata
|
# get list of available signature files in metadata
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
# orig_apk = os.path.join(tmpdir, 'orig.apk')
|
|
||||||
# os.rename(apkpath, orig_apk)
|
|
||||||
apkwithnewsig = os.path.join(tmpdir, 'newsig.apk')
|
apkwithnewsig = os.path.join(tmpdir, 'newsig.apk')
|
||||||
with ZipFile(apkpath, 'r') as in_apk:
|
with ZipFile(apkpath, 'r') as in_apk:
|
||||||
with ZipFile(apkwithnewsig, 'w') as out_apk:
|
with ZipFile(apkwithnewsig, 'w') as out_apk:
|
||||||
for sig_file in [signaturefile, signedfile, manifest]:
|
for sig_file in [signaturefile, signedfile, manifest]:
|
||||||
out_apk.write(sig_file, arcname='META-INF/' +
|
with open(sig_file, 'rb') as fp:
|
||||||
os.path.basename(sig_file))
|
buf = fp.read()
|
||||||
for f in in_apk.infolist():
|
info = zipfile.ZipInfo('META-INF/' + os.path.basename(sig_file))
|
||||||
if not apk_sigfile.match(f.filename):
|
info.compress_type = zipfile.ZIP_DEFLATED
|
||||||
if f.filename != 'META-INF/MANIFEST.MF':
|
info.create_system = 0 # "Windows" aka "FAT", what Android SDK uses
|
||||||
buf = in_apk.read(f.filename)
|
out_apk.writestr(info, buf)
|
||||||
out_apk.writestr(f.filename, buf)
|
for info in in_apk.infolist():
|
||||||
|
if not apk_sigfile.match(info.filename):
|
||||||
|
if info.filename != 'META-INF/MANIFEST.MF':
|
||||||
|
buf = in_apk.read(info.filename)
|
||||||
|
out_apk.writestr(info, buf)
|
||||||
os.remove(apkpath)
|
os.remove(apkpath)
|
||||||
p = SdkToolsPopen(['zipalign', '-v', '4', apkwithnewsig, apkpath])
|
p = SdkToolsPopen(['zipalign', '-v', '4', apkwithnewsig, apkpath])
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
|
@ -380,8 +380,8 @@ class FieldValidator():
|
|||||||
values = [v]
|
values = [v]
|
||||||
for v in values:
|
for v in values:
|
||||||
if not self.compiled.match(v):
|
if not self.compiled.match(v):
|
||||||
warn_or_exception("'%s' is not a valid %s in %s. Regex pattern: %s"
|
warn_or_exception(_("'{value}' is not a valid {field} in {appid}. Regex pattern: {pattern}")
|
||||||
% (v, self.name, appid, self.matching))
|
.format(value=v, field=self.name, appid=appid, pattern=self.matching))
|
||||||
|
|
||||||
|
|
||||||
# Generic value types
|
# Generic value types
|
||||||
@ -534,7 +534,7 @@ class DescriptionFormatter:
|
|||||||
if txt.startswith("[["):
|
if txt.startswith("[["):
|
||||||
index = txt.find("]]")
|
index = txt.find("]]")
|
||||||
if index == -1:
|
if index == -1:
|
||||||
warn_or_exception("Unterminated ]]")
|
warn_or_exception(_("Unterminated ]]"))
|
||||||
url = txt[2:index]
|
url = txt[2:index]
|
||||||
if self.linkResolver:
|
if self.linkResolver:
|
||||||
url, urltext = self.linkResolver(url)
|
url, urltext = self.linkResolver(url)
|
||||||
@ -546,7 +546,7 @@ class DescriptionFormatter:
|
|||||||
else:
|
else:
|
||||||
index = txt.find("]")
|
index = txt.find("]")
|
||||||
if index == -1:
|
if index == -1:
|
||||||
warn_or_exception("Unterminated ]")
|
warn_or_exception(_("Unterminated ]"))
|
||||||
url = txt[1:index]
|
url = txt[1:index]
|
||||||
index2 = url.find(' ')
|
index2 = url.find(' ')
|
||||||
if index2 == -1:
|
if index2 == -1:
|
||||||
@ -555,7 +555,7 @@ class DescriptionFormatter:
|
|||||||
urltxt = url[index2 + 1:]
|
urltxt = url[index2 + 1:]
|
||||||
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 brackets: [URL]"))
|
||||||
res_html += '<a href="' + url + '">' + html.escape(urltxt, quote=False) + '</a>'
|
res_html += '<a href="' + url + '">' + html.escape(urltxt, quote=False) + '</a>'
|
||||||
res_plain += urltxt
|
res_plain += urltxt
|
||||||
if urltxt != url:
|
if urltxt != url:
|
||||||
@ -664,7 +664,7 @@ def parse_srclib(metadatapath):
|
|||||||
try:
|
try:
|
||||||
f, v = line.split(':', 1)
|
f, v = line.split(':', 1)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
warn_or_exception("Invalid metadata in %s:%d" % (line, n))
|
warn_or_exception(_("Invalid metadata in %s:%d") % (line, n))
|
||||||
|
|
||||||
if f == "Subdir":
|
if f == "Subdir":
|
||||||
thisinfo[f] = v.split(',')
|
thisinfo[f] = v.split(',')
|
||||||
@ -734,7 +734,8 @@ def read_metadata(xref=True, check_vcs=[]):
|
|||||||
+ glob.glob('.fdroid.yml')):
|
+ glob.glob('.fdroid.yml')):
|
||||||
packageName, _ignored = fdroidserver.common.get_extension(os.path.basename(metadatapath))
|
packageName, _ignored = fdroidserver.common.get_extension(os.path.basename(metadatapath))
|
||||||
if packageName in apps:
|
if packageName in apps:
|
||||||
warn_or_exception("Found multiple metadata files for " + packageName)
|
warn_or_exception(_("Found multiple metadata files for {appid}")
|
||||||
|
.format(path=packageName))
|
||||||
app = parse_metadata(metadatapath, packageName in check_vcs)
|
app = parse_metadata(metadatapath, packageName in check_vcs)
|
||||||
check_metadata(app)
|
check_metadata(app)
|
||||||
apps[app.id] = app
|
apps[app.id] = app
|
||||||
@ -745,14 +746,14 @@ def read_metadata(xref=True, check_vcs=[]):
|
|||||||
def linkres(appid):
|
def linkres(appid):
|
||||||
if appid in apps:
|
if appid in apps:
|
||||||
return ("fdroid.app:" + appid, "Dummy name - don't know yet")
|
return ("fdroid.app:" + appid, "Dummy name - don't know yet")
|
||||||
warn_or_exception("Cannot resolve app id " + appid)
|
warn_or_exception(_("Cannot resolve app id {appid}").format(appid=appid))
|
||||||
|
|
||||||
for appid, app in apps.items():
|
for appid, app in apps.items():
|
||||||
try:
|
try:
|
||||||
description_html(app.Description, linkres)
|
description_html(app.Description, linkres)
|
||||||
except MetaDataException as e:
|
except MetaDataException as e:
|
||||||
warn_or_exception("Problem with description of " + appid +
|
warn_or_exception(_("Problem with description of {appid}: {error}")
|
||||||
" - " + str(e))
|
.format(appid=appid, error=str(e)))
|
||||||
|
|
||||||
return apps
|
return apps
|
||||||
|
|
||||||
@ -795,7 +796,8 @@ def get_default_app_info(metadatapath=None):
|
|||||||
manifestroot = fdroidserver.common.parse_xml(os.path.join(root, 'AndroidManifest.xml'))
|
manifestroot = fdroidserver.common.parse_xml(os.path.join(root, 'AndroidManifest.xml'))
|
||||||
break
|
break
|
||||||
if manifestroot is None:
|
if manifestroot is None:
|
||||||
warn_or_exception("Cannot find a packageName for {0}!".format(metadatapath))
|
warn_or_exception(_("Cannot find a packageName for {path}!")
|
||||||
|
.format(path=metadatapath))
|
||||||
appid = manifestroot.attrib['package']
|
appid = manifestroot.attrib['package']
|
||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
@ -915,17 +917,17 @@ def _decode_bool(s):
|
|||||||
return True
|
return True
|
||||||
if bool_false.match(s):
|
if bool_false.match(s):
|
||||||
return False
|
return False
|
||||||
warn_or_exception("Invalid bool '%s'" % s)
|
warn_or_exception(_("Invalid boolean '%s'") % s)
|
||||||
|
|
||||||
|
|
||||||
def parse_metadata(metadatapath, check_vcs=False):
|
def parse_metadata(metadatapath, check_vcs=False):
|
||||||
'''parse metadata file, optionally checking the git repo for metadata first'''
|
'''parse metadata file, optionally checking the git repo for metadata first'''
|
||||||
|
|
||||||
_, ext = fdroidserver.common.get_extension(metadatapath)
|
_ignored, ext = fdroidserver.common.get_extension(metadatapath)
|
||||||
accepted = fdroidserver.common.config['accepted_formats']
|
accepted = fdroidserver.common.config['accepted_formats']
|
||||||
if ext not in accepted:
|
if ext not in accepted:
|
||||||
warn_or_exception('"%s" is not an accepted format, convert to: %s' % (
|
warn_or_exception(_('"{path}" is not an accepted format, convert to: {formats}')
|
||||||
metadatapath, ', '.join(accepted)))
|
.format(path=metadatapath, formats=', '.join(accepted)))
|
||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
app.metadatapath = metadatapath
|
app.metadatapath = metadatapath
|
||||||
@ -943,7 +945,8 @@ def parse_metadata(metadatapath, check_vcs=False):
|
|||||||
elif ext == 'yml':
|
elif ext == 'yml':
|
||||||
parse_yaml_metadata(mf, app)
|
parse_yaml_metadata(mf, app)
|
||||||
else:
|
else:
|
||||||
warn_or_exception('Unknown metadata format: %s' % metadatapath)
|
warn_or_exception(_('Unknown metadata format: {path}')
|
||||||
|
.format(path=metadatapath))
|
||||||
|
|
||||||
if check_vcs and app.Repo:
|
if check_vcs and app.Repo:
|
||||||
build_dir = fdroidserver.common.get_build_dir(app)
|
build_dir = fdroidserver.common.get_build_dir(app)
|
||||||
@ -970,7 +973,7 @@ def parse_metadata(metadatapath, check_vcs=False):
|
|||||||
else:
|
else:
|
||||||
root_dir = '.'
|
root_dir = '.'
|
||||||
paths = fdroidserver.common.manifest_paths(root_dir, build.gradle)
|
paths = fdroidserver.common.manifest_paths(root_dir, build.gradle)
|
||||||
_, _, app.id = fdroidserver.common.parse_androidmanifests(paths, app)
|
_ignored, _ignored, app.id = fdroidserver.common.parse_androidmanifests(paths, app)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
@ -1162,12 +1165,12 @@ def parse_txt_metadata(mf, app):
|
|||||||
|
|
||||||
def add_buildflag(p, build):
|
def add_buildflag(p, build):
|
||||||
if not p.strip():
|
if not p.strip():
|
||||||
warn_or_exception("Empty build flag at {1}"
|
warn_or_exception(_("Empty build flag at {linedesc}")
|
||||||
.format(buildlines[0], linedesc))
|
.format(linedesc=linedesc))
|
||||||
bv = p.split('=', 1)
|
bv = p.split('=', 1)
|
||||||
if len(bv) != 2:
|
if len(bv) != 2:
|
||||||
warn_or_exception("Invalid build flag at {0} in {1}"
|
warn_or_exception(_("Invalid build flag at {line} in {linedesc}")
|
||||||
.format(buildlines[0], linedesc))
|
.format(line=buildlines[0], linedesc=linedesc))
|
||||||
|
|
||||||
pk, pv = bv
|
pk, pv = bv
|
||||||
pk = pk.lstrip()
|
pk = pk.lstrip()
|
||||||
@ -1186,7 +1189,8 @@ def parse_txt_metadata(mf, app):
|
|||||||
v = "".join(lines)
|
v = "".join(lines)
|
||||||
parts = [p.replace("\\,", ",") for p in re.split(build_line_sep, v)]
|
parts = [p.replace("\\,", ",") for p in re.split(build_line_sep, v)]
|
||||||
if len(parts) < 3:
|
if len(parts) < 3:
|
||||||
warn_or_exception("Invalid build format: " + v + " in " + mf.name)
|
warn_or_exception(_("Invalid build format: {value} in {name}")
|
||||||
|
.format(value=v, name=mf.name))
|
||||||
build = Build()
|
build = Build()
|
||||||
build.versionName = parts[0]
|
build.versionName = parts[0]
|
||||||
build.versionCode = parts[1]
|
build.versionCode = parts[1]
|
||||||
@ -1214,7 +1218,8 @@ def parse_txt_metadata(mf, app):
|
|||||||
try:
|
try:
|
||||||
int(versionCode)
|
int(versionCode)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
warn_or_exception('Invalid versionCode: "' + versionCode + '" is not an integer!')
|
warn_or_exception(_('Invalid versionCode: "{versionCode}" is not an integer!')
|
||||||
|
.format(versionCode=versionCode))
|
||||||
|
|
||||||
def add_comments(key):
|
def add_comments(key):
|
||||||
if not curcomments:
|
if not curcomments:
|
||||||
@ -1247,8 +1252,8 @@ def parse_txt_metadata(mf, app):
|
|||||||
del buildlines[:]
|
del buildlines[:]
|
||||||
else:
|
else:
|
||||||
if not build.commit and not build.disable:
|
if not build.commit and not build.disable:
|
||||||
warn_or_exception("No commit specified for {0} in {1}"
|
warn_or_exception(_("No commit specified for {versionName} in {linedesc}")
|
||||||
.format(build.versionName, linedesc))
|
.format(versionName=build.versionName, linedesc=linedesc))
|
||||||
|
|
||||||
app.builds.append(build)
|
app.builds.append(build)
|
||||||
add_comments('build:' + build.versionCode)
|
add_comments('build:' + build.versionCode)
|
||||||
@ -1263,10 +1268,10 @@ def parse_txt_metadata(mf, app):
|
|||||||
try:
|
try:
|
||||||
f, v = line.split(':', 1)
|
f, v = line.split(':', 1)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
warn_or_exception("Invalid metadata in " + linedesc)
|
warn_or_exception(_("Invalid metadata in: ") + linedesc)
|
||||||
|
|
||||||
if f not in app_fields:
|
if f not in app_fields:
|
||||||
warn_or_exception('Unrecognised app field: ' + f)
|
warn_or_exception(_('Unrecognised app field: ') + f)
|
||||||
|
|
||||||
# Translate obsolete fields...
|
# Translate obsolete fields...
|
||||||
if f == 'Market Version':
|
if f == 'Market Version':
|
||||||
@ -1282,8 +1287,8 @@ def parse_txt_metadata(mf, app):
|
|||||||
if ftype == TYPE_MULTILINE:
|
if ftype == TYPE_MULTILINE:
|
||||||
mode = 1
|
mode = 1
|
||||||
if v:
|
if v:
|
||||||
warn_or_exception("Unexpected text on same line as "
|
warn_or_exception(_("Unexpected text on same line as {field} in {linedesc}")
|
||||||
+ f + " in " + linedesc)
|
.format(field=f, linedesc=linedesc))
|
||||||
elif ftype == TYPE_STRING:
|
elif ftype == TYPE_STRING:
|
||||||
app[f] = v
|
app[f] = v
|
||||||
elif ftype == TYPE_LIST:
|
elif ftype == TYPE_LIST:
|
||||||
@ -1300,24 +1305,26 @@ def parse_txt_metadata(mf, app):
|
|||||||
elif ftype == TYPE_BUILD_V2:
|
elif ftype == TYPE_BUILD_V2:
|
||||||
vv = v.split(',')
|
vv = v.split(',')
|
||||||
if len(vv) != 2:
|
if len(vv) != 2:
|
||||||
warn_or_exception('Build should have comma-separated',
|
warn_or_exception(_('Build should have comma-separated '
|
||||||
'versionName and versionCode,',
|
'versionName and versionCode, '
|
||||||
'not "{0}", in {1}'.format(v, linedesc))
|
'not "{value}", in {linedesc}')
|
||||||
|
.format(value=v, linedesc=linedesc))
|
||||||
build = Build()
|
build = Build()
|
||||||
build.versionName = vv[0]
|
build.versionName = vv[0]
|
||||||
build.versionCode = vv[1]
|
build.versionCode = vv[1]
|
||||||
check_versionCode(build.versionCode)
|
check_versionCode(build.versionCode)
|
||||||
|
|
||||||
if build.versionCode in vc_seen:
|
if build.versionCode in vc_seen:
|
||||||
warn_or_exception('Duplicate build recipe found for versionCode %s in %s'
|
warn_or_exception(_('Duplicate build recipe found for versionCode {versionCode} in {linedesc}')
|
||||||
% (build.versionCode, linedesc))
|
.format(versionCode=build.versionCode, linedesc=linedesc))
|
||||||
vc_seen.add(build.versionCode)
|
vc_seen.add(build.versionCode)
|
||||||
del buildlines[:]
|
del buildlines[:]
|
||||||
mode = 3
|
mode = 3
|
||||||
elif ftype == TYPE_OBSOLETE:
|
elif ftype == TYPE_OBSOLETE:
|
||||||
pass # Just throw it away!
|
pass # Just throw it away!
|
||||||
else:
|
else:
|
||||||
warn_or_exception("Unrecognised field '" + f + "' in " + linedesc)
|
warn_or_exception(_("Unrecognised field '{field}' in {linedesc}")
|
||||||
|
.format(field=f, linedesc=linedesc))
|
||||||
elif mode == 1: # Multiline field
|
elif mode == 1: # Multiline field
|
||||||
if line == '.':
|
if line == '.':
|
||||||
mode = 0
|
mode = 0
|
||||||
@ -1338,11 +1345,14 @@ def parse_txt_metadata(mf, app):
|
|||||||
|
|
||||||
# Mode at end of file should always be 0
|
# Mode at end of file should always be 0
|
||||||
if mode == 1:
|
if mode == 1:
|
||||||
warn_or_exception(f + " not terminated in " + mf.name)
|
warn_or_exception(_("{field} not terminated in {name}")
|
||||||
|
.format(field=f, name=mf.name))
|
||||||
if mode == 2:
|
if mode == 2:
|
||||||
warn_or_exception("Unterminated continuation in " + mf.name)
|
warn_or_exception(_("Unterminated continuation in {name}")
|
||||||
|
.format(name=mf.name))
|
||||||
if mode == 3:
|
if mode == 3:
|
||||||
warn_or_exception("Unterminated build in " + mf.name)
|
warn_or_exception(_("Unterminated build in {name}")
|
||||||
|
.format(name=mf.name))
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
@ -1498,11 +1508,11 @@ def write_txt(mf, app):
|
|||||||
|
|
||||||
|
|
||||||
def write_metadata(metadatapath, app):
|
def write_metadata(metadatapath, app):
|
||||||
_, ext = fdroidserver.common.get_extension(metadatapath)
|
_ignored, ext = fdroidserver.common.get_extension(metadatapath)
|
||||||
accepted = fdroidserver.common.config['accepted_formats']
|
accepted = fdroidserver.common.config['accepted_formats']
|
||||||
if ext not in accepted:
|
if ext not in accepted:
|
||||||
warn_or_exception('Cannot write "%s", not an accepted format, use: %s'
|
warn_or_exception(_('Cannot write "{path}", not an accepted format, use: {formats}')
|
||||||
% (metadatapath, ', '.join(accepted)))
|
.format(path=metadatapath, formats=', '.join(accepted)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(metadatapath, 'w', encoding='utf8') as mf:
|
with open(metadatapath, 'w', encoding='utf8') as mf:
|
||||||
@ -1514,7 +1524,7 @@ def write_metadata(metadatapath, app):
|
|||||||
os.remove(metadatapath)
|
os.remove(metadatapath)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
warn_or_exception('Unknown metadata format: %s' % metadatapath)
|
warn_or_exception(_('Unknown metadata format: %s') % metadatapath)
|
||||||
|
|
||||||
|
|
||||||
def add_metadata_arguments(parser):
|
def add_metadata_arguments(parser):
|
||||||
|
@ -185,7 +185,7 @@ def scan_source(build_dir, build):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
path_in_build_dir = os.path.relpath(filepath, build_dir)
|
path_in_build_dir = os.path.relpath(filepath, build_dir)
|
||||||
_, ext = common.get_extension(path_in_build_dir)
|
_ignored, ext = common.get_extension(path_in_build_dir)
|
||||||
|
|
||||||
if ext == 'so':
|
if ext == 'so':
|
||||||
count += handleproblem('shared library', path_in_build_dir, filepath)
|
count += handleproblem('shared library', path_in_build_dir, filepath)
|
||||||
|
@ -824,7 +824,7 @@ def insert_localized_app_metadata(apps):
|
|||||||
locale = segments[-2]
|
locale = segments[-2]
|
||||||
destdir = os.path.join('repo', packageName, locale)
|
destdir = os.path.join('repo', packageName, locale)
|
||||||
for f in glob.glob(os.path.join(root, d, '*.*')):
|
for f in glob.glob(os.path.join(root, d, '*.*')):
|
||||||
_, extension = common.get_extension(f)
|
_ignored, extension = common.get_extension(f)
|
||||||
if extension in ALLOWED_EXTENSIONS:
|
if extension in ALLOWED_EXTENSIONS:
|
||||||
screenshotdestdir = os.path.join(destdir, d)
|
screenshotdestdir = os.path.join(destdir, d)
|
||||||
os.makedirs(screenshotdestdir, mode=0o755, exist_ok=True)
|
os.makedirs(screenshotdestdir, mode=0o755, exist_ok=True)
|
||||||
@ -846,24 +846,24 @@ def insert_localized_app_metadata(apps):
|
|||||||
base, extension = common.get_extension(filename)
|
base, extension = common.get_extension(filename)
|
||||||
|
|
||||||
if packageName not in apps:
|
if packageName not in apps:
|
||||||
logging.warning('Found "%s" graphic without metadata for app "%s"!'
|
logging.warning(_('Found "{path}" graphic without metadata for app "{name}"!')
|
||||||
% (filename, packageName))
|
.format(path=filename, name=packageName))
|
||||||
continue
|
continue
|
||||||
graphics = _get_localized_dict(apps[packageName], locale)
|
graphics = _get_localized_dict(apps[packageName], locale)
|
||||||
|
|
||||||
if extension not in ALLOWED_EXTENSIONS:
|
if extension not in ALLOWED_EXTENSIONS:
|
||||||
logging.warning('Only PNG and JPEG are supported for graphics, found: ' + f)
|
logging.warning(_('Only PNG and JPEG are supported for graphics, found: {path}').format(path=f))
|
||||||
elif base in GRAPHIC_NAMES:
|
elif base in GRAPHIC_NAMES:
|
||||||
# there can only be zero or one of these per locale
|
# there can only be zero or one of these per locale
|
||||||
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 to ' + screenshotdir + ': ' + f)
|
logging.debug(_('adding to {name}: {path}').format(name=screenshotdir, path=f))
|
||||||
if screenshotdir not in graphics:
|
if screenshotdir not in graphics:
|
||||||
graphics[screenshotdir] = []
|
graphics[screenshotdir] = []
|
||||||
graphics[screenshotdir].append(filename)
|
graphics[screenshotdir].append(filename)
|
||||||
else:
|
else:
|
||||||
logging.warning('Unsupported graphics file found: ' + f)
|
logging.warning(_('Unsupported graphics file found: {path}').format(path=f))
|
||||||
|
|
||||||
|
|
||||||
def scan_repo_files(apkcache, repodir, knownapks, use_date_from_file=False):
|
def scan_repo_files(apkcache, repodir, knownapks, use_date_from_file=False):
|
||||||
@ -1625,7 +1625,7 @@ def move_apk_between_sections(from_dir, to_dir, apk):
|
|||||||
for density in all_screen_densities:
|
for density in all_screen_densities:
|
||||||
from_icon_dir = get_icon_dir(from_dir, density)
|
from_icon_dir = get_icon_dir(from_dir, density)
|
||||||
to_icon_dir = get_icon_dir(to_dir, density)
|
to_icon_dir = get_icon_dir(to_dir, density)
|
||||||
if density not in apk['icons']:
|
if density not in apk.get('icons', []):
|
||||||
continue
|
continue
|
||||||
_move_file(from_icon_dir, to_icon_dir, apk['icons'][density], True)
|
_move_file(from_icon_dir, to_icon_dir, apk['icons'][density], True)
|
||||||
if 'srcname' in apk:
|
if 'srcname' in apk:
|
||||||
|
@ -74,4 +74,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(BuildTest))
|
newSuite.addTest(unittest.makeSuite(BuildTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -92,6 +92,41 @@ class CommonTest(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
print('no build-tools found: ' + build_tools)
|
print('no build-tools found: ' + build_tools)
|
||||||
|
|
||||||
|
def test_find_java_root_path(self):
|
||||||
|
tmptestsdir = tempfile.mkdtemp(prefix='test_find_java_root_path', dir=self.tmpdir)
|
||||||
|
os.chdir(tmptestsdir)
|
||||||
|
|
||||||
|
all_pathlists = [
|
||||||
|
([ # Debian
|
||||||
|
'/usr/lib/jvm/java-1.5.0-gcj-5-amd64',
|
||||||
|
'/usr/lib/jvm/java-8-openjdk-amd64',
|
||||||
|
'/usr/lib/jvm/java-1.8.0-openjdk-amd64',
|
||||||
|
], '/usr/lib/jvm/java-8-openjdk-amd64'),
|
||||||
|
([ # OSX
|
||||||
|
'/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk',
|
||||||
|
'/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk',
|
||||||
|
'/System/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk',
|
||||||
|
], '/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk'),
|
||||||
|
]
|
||||||
|
|
||||||
|
for pathlist, choice in all_pathlists:
|
||||||
|
# strip leading / to make relative paths to test without root
|
||||||
|
pathlist = [p[1:] for p in pathlist]
|
||||||
|
|
||||||
|
# create test file used in common._add_java_paths_to_config()
|
||||||
|
for p in pathlist:
|
||||||
|
if p.startswith('/System') or p.startswith('/Library'):
|
||||||
|
basedir = os.path.join(p, 'Contents', 'Home', 'bin')
|
||||||
|
else:
|
||||||
|
basedir = os.path.join(p, 'bin')
|
||||||
|
os.makedirs(basedir)
|
||||||
|
open(os.path.join(basedir, 'javac'), 'w').close()
|
||||||
|
|
||||||
|
config = dict()
|
||||||
|
config['java_paths'] = dict()
|
||||||
|
fdroidserver.common._add_java_paths_to_config(pathlist, config)
|
||||||
|
self.assertEqual(config['java_paths']['8'], choice[1:])
|
||||||
|
|
||||||
def testIsApkDebuggable(self):
|
def testIsApkDebuggable(self):
|
||||||
config = dict()
|
config = dict()
|
||||||
fdroidserver.common.fill_config_defaults(config)
|
fdroidserver.common.fill_config_defaults(config)
|
||||||
@ -177,7 +212,7 @@ class CommonTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_prepare_sources_refresh(self):
|
def test_prepare_sources_refresh(self):
|
||||||
packageName = 'org.fdroid.ci.test.app'
|
packageName = 'org.fdroid.ci.test.app'
|
||||||
testdir = tempfile.mkdtemp(prefix='test_verify_apks', dir=self.tmpdir)
|
testdir = tempfile.mkdtemp(prefix='test_prepare_sources_refresh', dir=self.tmpdir)
|
||||||
print('testdir', testdir)
|
print('testdir', testdir)
|
||||||
os.chdir(testdir)
|
os.chdir(testdir)
|
||||||
os.mkdir('build')
|
os.mkdir('build')
|
||||||
@ -462,4 +497,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(CommonTest))
|
newSuite.addTest(unittest.makeSuite(CommonTest))
|
||||||
unittest.main()
|
unittest.main(failfast=True)
|
||||||
|
@ -62,4 +62,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(ExceptionTest))
|
newSuite.addTest(unittest.makeSuite(ExceptionTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -54,4 +54,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(ImportTest))
|
newSuite.addTest(unittest.makeSuite(ImportTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -236,4 +236,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(IndexTest))
|
newSuite.addTest(unittest.makeSuite(IndexTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -43,4 +43,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(InstallTest))
|
newSuite.addTest(unittest.makeSuite(InstallTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -53,4 +53,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(LintTest))
|
newSuite.addTest(unittest.makeSuite(LintTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -129,4 +129,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(MetadataTest))
|
newSuite.addTest(unittest.makeSuite(MetadataTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -144,4 +144,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(PublishTest))
|
newSuite.addTest(unittest.makeSuite(PublishTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -62,4 +62,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(SignaturesTest))
|
newSuite.addTest(unittest.makeSuite(SignaturesTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
@ -576,4 +576,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
newSuite = unittest.TestSuite()
|
newSuite = unittest.TestSuite()
|
||||||
newSuite.addTest(unittest.makeSuite(UpdateTest))
|
newSuite.addTest(unittest.makeSuite(UpdateTest))
|
||||||
unittest.main()
|
unittest.main(failfast=False)
|
||||||
|
Loading…
Reference in New Issue
Block a user