diff --git a/fdroidserver/build.py b/fdroidserver/build.py
index d02947bd..daf109dd 100644
--- a/fdroidserver/build.py
+++ b/fdroidserver/build.py
@@ -981,7 +981,9 @@ def parse_commandline():
help="Build all applications available")
parser.add_argument("-w", "--wiki", default=False, action="store_true",
help="Update the wiki")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
# Force --stop with --on-server to get correct exit code
if options.onserver:
diff --git a/fdroidserver/checkupdates.py b/fdroidserver/checkupdates.py
index e22a6e0f..b754bf10 100644
--- a/fdroidserver/checkupdates.py
+++ b/fdroidserver/checkupdates.py
@@ -524,7 +524,9 @@ def main():
help="Commit changes")
parser.add_argument("--gplay", action="store_true", default=False,
help="Only print differences with the Play Store")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/import.py b/fdroidserver/import.py
index 8c7f5107..97c82f6f 100644
--- a/fdroidserver/import.py
+++ b/fdroidserver/import.py
@@ -170,7 +170,9 @@ def main():
help="Path to main android project subdirectory, if not in root.")
parser.add_argument("--rev", default=None,
help="Allows a different revision (or git branch) to be specified for the initial import")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/lint.py b/fdroidserver/lint.py
index c805288f..41d4b21f 100644
--- a/fdroidserver/lint.py
+++ b/fdroidserver/lint.py
@@ -377,7 +377,9 @@ def main():
parser.add_argument("-f", "--format", action="store_true", default=False,
help="Also warn about formatting issues, like rewritemeta -l")
parser.add_argument("appid", nargs='*', help="app-id in the form APPID")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/metadata.py b/fdroidserver/metadata.py
index f20b2230..e03efbee 100644
--- a/fdroidserver/metadata.py
+++ b/fdroidserver/metadata.py
@@ -41,6 +41,7 @@ import xml.etree.cElementTree as ElementTree
import fdroidserver.common
srclibs = None
+warnings_action = None
class MetaDataException(Exception):
@@ -51,6 +52,17 @@ class MetaDataException(Exception):
def __str__(self):
return self.value
+
+def warn_or_exception(value):
+ '''output warning or Exception depending on -W'''
+ if warnings_action == 'ignore':
+ pass
+ elif warnings_action == 'error':
+ raise MetaDataException(value)
+ else:
+ logging.warn(value)
+
+
# To filter which ones should be written to the metadata files if
# present
app_fields = set([
@@ -173,14 +185,14 @@ class App():
# Gets the value associated to a field name, e.g. 'Auto Name'
def get_field(self, f):
if f not in app_fields:
- raise MetaDataException('Unrecognised app field: ' + f)
+ warn_or_exception('Unrecognised app field: ' + f)
k = App.field_to_attr(f)
return getattr(self, k)
# Sets the value associated to a field name, e.g. 'Auto Name'
def set_field(self, f, v):
if f not in app_fields:
- raise MetaDataException('Unrecognised app field: ' + f)
+ warn_or_exception('Unrecognised app field: ' + f)
k = App.field_to_attr(f)
self.__dict__[k] = v
self._modified.add(k)
@@ -188,7 +200,7 @@ class App():
# Appends to the value associated to a field name, e.g. 'Auto Name'
def append_field(self, f, v):
if f not in app_fields:
- raise MetaDataException('Unrecognised app field: ' + f)
+ warn_or_exception('Unrecognised app field: ' + f)
k = App.field_to_attr(f)
if k not in self.__dict__:
self.__dict__[k] = [v]
@@ -307,7 +319,7 @@ class Build():
def get_flag(self, f):
if f not in build_flags:
- raise MetaDataException('Unrecognised build flag: ' + f)
+ warn_or_exception('Unrecognised build flag: ' + f)
return getattr(self, f)
def set_flag(self, f, v):
@@ -316,13 +328,13 @@ class Build():
if f == 'versionCode':
f = 'vercode'
if f not in build_flags:
- raise MetaDataException('Unrecognised build flag: ' + f)
+ warn_or_exception('Unrecognised build flag: ' + f)
self.__dict__[f] = v
self._modified.add(f)
def append_flag(self, f, v):
if f not in build_flags:
- raise MetaDataException('Unrecognised build flag: ' + f)
+ warn_or_exception('Unrecognised build flag: ' + f)
if f not in self.__dict__:
self.__dict__[f] = [v]
else:
@@ -414,8 +426,8 @@ class FieldValidator():
values = [v]
for v in values:
if not self.compiled.match(v):
- raise MetaDataException("'%s' is not a valid %s in %s. Regex pattern: %s"
- % (v, self.name, appid, self.matching))
+ warn_or_exception("'%s' is not a valid %s in %s. Regex pattern: %s"
+ % (v, self.name, appid, self.matching))
# Generic value types
valuetypes = {
@@ -588,7 +600,7 @@ class DescriptionFormatter:
if txt.startswith("[["):
index = txt.find("]]")
if index == -1:
- raise MetaDataException("Unterminated ]]")
+ warn_or_exception("Unterminated ]]")
url = txt[2:index]
if self.linkResolver:
url, urltext = self.linkResolver(url)
@@ -600,7 +612,7 @@ class DescriptionFormatter:
else:
index = txt.find("]")
if index == -1:
- raise MetaDataException("Unterminated ]")
+ warn_or_exception("Unterminated ]")
url = txt[1:index]
index2 = url.find(' ')
if index2 == -1:
@@ -609,7 +621,7 @@ class DescriptionFormatter:
urltxt = url[index2 + 1:]
url = url[:index2]
if url == urltxt:
- raise MetaDataException("Url title is just the URL - use [url]")
+ warn_or_exception("Url title is just the URL - use [url]")
res_html += '' + cgi.escape(urltxt) + ''
res_plain += urltxt
if urltxt != url:
@@ -718,7 +730,7 @@ def parse_srclib(metadatapath):
try:
f, v = line.split(':', 1)
except ValueError:
- raise MetaDataException("Invalid metadata in %s:%d" % (line, n))
+ warn_or_exception("Invalid metadata in %s:%d" % (line, n))
if f == "Subdir":
thisinfo[f] = v.split(',')
@@ -785,7 +797,7 @@ def read_metadata(xref=True):
+ glob.glob('.fdroid.yml')):
packageName, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath))
if packageName in apps:
- raise MetaDataException("Found multiple metadata files for " + packageName)
+ warn_or_exception("Found multiple metadata files for " + packageName)
app = parse_metadata(metadatapath)
check_metadata(app)
apps[app.id] = app
@@ -796,14 +808,14 @@ def read_metadata(xref=True):
def linkres(appid):
if appid in apps:
return ("fdroid.app:" + appid, "Dummy name - don't know yet")
- raise MetaDataException("Cannot resolve app id " + appid)
+ warn_or_exception("Cannot resolve app id " + appid)
for appid, app in apps.items():
try:
description_html(app.Description, linkres)
except MetaDataException as e:
- raise MetaDataException("Problem with description of " + appid +
- " - " + str(e))
+ warn_or_exception("Problem with description of " + appid +
+ " - " + str(e))
return apps
@@ -845,7 +857,7 @@ def get_default_app_info(metadatapath=None):
manifestroot = fdroidserver.common.parse_xml(os.path.join(root, 'AndroidManifest.xml'))
break
if manifestroot is None:
- raise MetaDataException("Cannot find a packageName for {0}!".format(metadatapath))
+ warn_or_exception("Cannot find a packageName for {0}!".format(metadatapath))
appid = manifestroot.attrib['package']
app = App()
@@ -930,14 +942,14 @@ def _decode_bool(s):
return True
if bool_false.match(s):
return False
- raise MetaDataException("Invalid bool '%s'" % s)
+ warn_or_exception("Invalid bool '%s'" % s)
def parse_metadata(metadatapath):
_, ext = fdroidserver.common.get_extension(metadatapath)
accepted = fdroidserver.common.config['accepted_formats']
if ext not in accepted:
- raise MetaDataException('"%s" is not an accepted format, convert to: %s' % (
+ warn_or_exception('"%s" is not an accepted format, convert to: %s' % (
metadatapath, ', '.join(accepted)))
app = App()
@@ -954,7 +966,7 @@ def parse_metadata(metadatapath):
elif ext == 'yml':
parse_yaml_metadata(mf, app)
else:
- raise MetaDataException('Unknown metadata format: %s' % metadatapath)
+ warn_or_exception('Unknown metadata format: %s' % metadatapath)
post_metadata_parse(app)
return app
@@ -979,7 +991,7 @@ def parse_xml_metadata(mf, app):
root = tree.getroot()
if root.tag != 'resources':
- raise MetaDataException('resources file does not have root element ')
+ warn_or_exception('resources file does not have root element ')
for child in root:
if child.tag != 'builds':
@@ -1022,12 +1034,12 @@ def parse_txt_metadata(mf, app):
def add_buildflag(p, build):
if not p.strip():
- raise MetaDataException("Empty build flag at {1}"
- .format(buildlines[0], linedesc))
+ warn_or_exception("Empty build flag at {1}"
+ .format(buildlines[0], linedesc))
bv = p.split('=', 1)
if len(bv) != 2:
- raise MetaDataException("Invalid build flag at {0} in {1}"
- .format(buildlines[0], linedesc))
+ warn_or_exception("Invalid build flag at {0} in {1}"
+ .format(buildlines[0], linedesc))
pk, pv = bv
pk = pk.lstrip()
@@ -1044,7 +1056,7 @@ def parse_txt_metadata(mf, app):
v = "".join(lines)
parts = [p.replace("\\,", ",") for p in re.split(build_line_sep, v)]
if len(parts) < 3:
- raise MetaDataException("Invalid build format: " + v + " in " + mf.name)
+ warn_or_exception("Invalid build format: " + v + " in " + mf.name)
build = Build()
build.version = parts[0]
build.vercode = parts[1]
@@ -1095,8 +1107,8 @@ def parse_txt_metadata(mf, app):
del buildlines[:]
else:
if not build.commit and not build.disable:
- raise MetaDataException("No commit specified for {0} in {1}"
- .format(build.version, linedesc))
+ warn_or_exception("No commit specified for {0} in {1}"
+ .format(build.version, linedesc))
app.builds.append(build)
add_comments('build:' + build.vercode)
@@ -1111,7 +1123,7 @@ def parse_txt_metadata(mf, app):
try:
f, v = line.split(':', 1)
except ValueError:
- raise MetaDataException("Invalid metadata in " + linedesc)
+ warn_or_exception("Invalid metadata in " + linedesc)
# Translate obsolete fields...
if f == 'Market Version':
@@ -1125,7 +1137,8 @@ def parse_txt_metadata(mf, app):
if ftype == TYPE_MULTILINE:
mode = 1
if v:
- raise MetaDataException("Unexpected text on same line as " + f + " in " + linedesc)
+ warn_or_exception("Unexpected text on same line as "
+ + f + " in " + linedesc)
elif ftype == TYPE_STRING:
app.set_field(f, v)
elif ftype == TYPE_LIST:
@@ -1142,21 +1155,22 @@ def parse_txt_metadata(mf, app):
elif ftype == TYPE_BUILD_V2:
vv = v.split(',')
if len(vv) != 2:
- raise MetaDataException('Build should have comma-separated version and vercode, not "{0}", in {1}'
- .format(v, linedesc))
+ warn_or_exception('Build should have comma-separated',
+ 'version and vercode,',
+ 'not "{0}", in {1}'.format(v, linedesc))
build = Build()
build.version = vv[0]
build.vercode = vv[1]
if build.vercode in vc_seen:
- raise MetaDataException('Duplicate build recipe found for vercode %s in %s' % (
- build.vercode, linedesc))
+ warn_or_exception('Duplicate build recipe found for vercode %s in %s'
+ % (build.vercode, linedesc))
vc_seen.add(build.vercode)
del buildlines[:]
mode = 3
elif ftype == TYPE_OBSOLETE:
pass # Just throw it away!
else:
- raise MetaDataException("Unrecognised field '" + f + "' in " + linedesc)
+ warn_or_exception("Unrecognised field '" + f + "' in " + linedesc)
elif mode == 1: # Multiline field
if line == '.':
mode = 0
@@ -1177,11 +1191,11 @@ def parse_txt_metadata(mf, app):
# Mode at end of file should always be 0
if mode == 1:
- raise MetaDataException(f + " not terminated in " + mf.name)
+ warn_or_exception(f + " not terminated in " + mf.name)
if mode == 2:
- raise MetaDataException("Unterminated continuation in " + mf.name)
+ warn_or_exception("Unterminated continuation in " + mf.name)
if mode == 3:
- raise MetaDataException("Unterminated build in " + mf.name)
+ warn_or_exception("Unterminated build in " + mf.name)
return app
@@ -1382,12 +1396,18 @@ def write_metadata(metadatapath, app):
_, ext = fdroidserver.common.get_extension(metadatapath)
accepted = fdroidserver.common.config['accepted_formats']
if ext not in accepted:
- raise MetaDataException('Cannot write "%s", not an accepted format, use: %s' % (
- metadatapath, ', '.join(accepted)))
+ warn_or_exception('Cannot write "%s", not an accepted format, use: %s'
+ % (metadatapath, ', '.join(accepted)))
with open(metadatapath, 'w', encoding='utf8') as mf:
if ext == 'txt':
return write_txt(mf, app)
elif ext == 'yml':
return write_yaml(mf, app)
- raise MetaDataException('Unknown metadata format: %s' % metadatapath)
+ warn_or_exception('Unknown metadata format: %s' % metadatapath)
+
+
+def add_metadata_arguments(parser):
+ '''add common command line flags related to metadata processing'''
+ parser.add_argument("-W", default='error',
+ help="force errors to be warnings, or ignore")
diff --git a/fdroidserver/publish.py b/fdroidserver/publish.py
index 668f19a3..62674480 100644
--- a/fdroidserver/publish.py
+++ b/fdroidserver/publish.py
@@ -42,7 +42,9 @@ def main():
"[APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versioncode in the form APPID[:VERCODE]")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/readmeta.py b/fdroidserver/readmeta.py
index e04b5623..88ac7be3 100644
--- a/fdroidserver/readmeta.py
+++ b/fdroidserver/readmeta.py
@@ -20,12 +20,16 @@ from argparse import ArgumentParser
from . import common
from . import metadata
+options = None
+
def main():
parser = ArgumentParser(usage="%(prog)s")
common.setup_global_opts(parser)
- parser.parse_args()
+ metadata.add_metadata_arguments(parser)
+ options = parser.parse_args()
+ metadata.warnings_action = options.W
common.read_config(None)
metadata.read_metadata(xref=True)
diff --git a/fdroidserver/rewritemeta.py b/fdroidserver/rewritemeta.py
index 65a50841..25ed0875 100644
--- a/fdroidserver/rewritemeta.py
+++ b/fdroidserver/rewritemeta.py
@@ -53,7 +53,9 @@ def main():
parser.add_argument("-t", "--to", default=None,
help="Rewrite to a specific format")
parser.add_argument("appid", nargs='*', help="app-id in the form APPID")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/scanner.py b/fdroidserver/scanner.py
index 41ecbb50..289e041a 100644
--- a/fdroidserver/scanner.py
+++ b/fdroidserver/scanner.py
@@ -250,7 +250,9 @@ def main():
parser = ArgumentParser(usage="%(prog)s [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versioncode in the form APPID[:VERCODE]")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/stats.py b/fdroidserver/stats.py
index 1a050033..1f822ba0 100644
--- a/fdroidserver/stats.py
+++ b/fdroidserver/stats.py
@@ -66,7 +66,9 @@ def main():
"have been made that would invalidate old cached data.")
parser.add_argument("--nologs", action="store_true", default=False,
help="Don't do anything logs-related")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)
diff --git a/fdroidserver/update.py b/fdroidserver/update.py
index b1ebfd35..7e1181d1 100644
--- a/fdroidserver/update.py
+++ b/fdroidserver/update.py
@@ -1316,7 +1316,9 @@ def main():
help="When configured for signed indexes, create only unsigned indexes at this stage")
parser.add_argument("--use-date-from-apk", action="store_true", default=False,
help="Use date from apk instead of current time for newly added apks")
+ metadata.add_metadata_arguments(parser)
options = parser.parse_args()
+ metadata.warnings_action = options.W
config = common.read_config(options)