exit with error if duplicate metadata file is found

In order to prevent confusion caused by multiple metadata files for a given
app, fdroid will exit with an error if it finds any app metadata file with
the same package ID as one that has already been parsed.
This commit is contained in:
Hans-Christoph Steiner 2015-08-05 12:53:17 +02:00
parent 6f334558df
commit 8d6e0aebb9
6 changed files with 82 additions and 17 deletions

View file

@ -494,23 +494,28 @@ def read_metadata(xref=True):
if not os.path.exists(basedir): if not os.path.exists(basedir):
os.makedirs(basedir) os.makedirs(basedir)
# If there are multiple metadata files for a single appid, then the first
# file that is parsed wins over all the others, and the rest throw an
# exception. So the original .txt format is parsed first, at least until
# newer formats stabilize.
for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.txt'))): for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.txt'))):
appid, appinfo = parse_txt_metadata(metadatapath) appid, appinfo = parse_txt_metadata(apps, metadatapath)
check_metadata(appinfo) check_metadata(appinfo)
apps[appid] = appinfo apps[appid] = appinfo
for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.json'))): for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.json'))):
appid, appinfo = parse_json_metadata(metadatapath) appid, appinfo = parse_json_metadata(apps, metadatapath)
check_metadata(appinfo) check_metadata(appinfo)
apps[appid] = appinfo apps[appid] = appinfo
for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.xml'))): for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.xml'))):
appid, appinfo = parse_xml_metadata(metadatapath) appid, appinfo = parse_xml_metadata(apps, metadatapath)
check_metadata(appinfo) check_metadata(appinfo)
apps[appid] = appinfo apps[appid] = appinfo
for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.yaml'))): for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.yaml'))):
appid, appinfo = parse_yaml_metadata(metadatapath) appid, appinfo = parse_yaml_metadata(apps, metadatapath)
check_metadata(appinfo) check_metadata(appinfo)
apps[appid] = appinfo apps[appid] = appinfo
@ -586,10 +591,16 @@ def split_list_values(s):
return [v for v in l if v] return [v for v in l if v]
def get_default_app_info_list(metadatapath): def get_default_app_info_list(apps, metadatapath):
appid = os.path.splitext(os.path.basename(metadatapath))[0] appid = os.path.splitext(os.path.basename(metadatapath))[0]
if appid in apps:
logging.critical("'%s' is a duplicate! '%s' is already provided by '%s'"
% (metadatapath, appid, apps[appid]['metadatapath']))
sys.exit(1)
thisinfo = {} thisinfo = {}
thisinfo.update(app_defaults) thisinfo.update(app_defaults)
thisinfo['metadatapath'] = metadatapath
if appid is not None: if appid is not None:
thisinfo['id'] = appid thisinfo['id'] = appid
@ -602,7 +613,7 @@ def get_default_app_info_list(metadatapath):
def post_metadata_parse(thisinfo): def post_metadata_parse(thisinfo):
supported_metadata = app_defaults.keys() + ['comments', 'builds', 'id'] supported_metadata = app_defaults.keys() + ['comments', 'builds', 'id', 'metadatapath']
for k, v in thisinfo.iteritems(): for k, v in thisinfo.iteritems():
if k not in supported_metadata: if k not in supported_metadata:
raise MetaDataException("Unrecognised metadata: {0}: {1}" raise MetaDataException("Unrecognised metadata: {0}: {1}"
@ -720,9 +731,9 @@ def _decode_dict(data):
return rv return rv
def parse_json_metadata(metadatapath): def parse_json_metadata(apps, metadatapath):
appid, thisinfo = get_default_app_info_list(metadatapath) appid, thisinfo = get_default_app_info_list(apps, metadatapath)
# fdroid metadata is only strings and booleans, no floats or ints. And # fdroid metadata is only strings and booleans, no floats or ints. And
# json returns unicode, and fdroidserver still uses plain python strings # json returns unicode, and fdroidserver still uses plain python strings
@ -737,9 +748,9 @@ def parse_json_metadata(metadatapath):
return (appid, thisinfo) return (appid, thisinfo)
def parse_xml_metadata(metadatapath): def parse_xml_metadata(apps, metadatapath):
appid, thisinfo = get_default_app_info_list(metadatapath) appid, thisinfo = get_default_app_info_list(apps, metadatapath)
tree = ElementTree.ElementTree(file=metadatapath) tree = ElementTree.ElementTree(file=metadatapath)
root = tree.getroot() root = tree.getroot()
@ -787,9 +798,9 @@ def parse_xml_metadata(metadatapath):
return (appid, thisinfo) return (appid, thisinfo)
def parse_yaml_metadata(metadatapath): def parse_yaml_metadata(apps, metadatapath):
appid, thisinfo = get_default_app_info_list(metadatapath) appid, thisinfo = get_default_app_info_list(apps, metadatapath)
yamlinfo = yaml.load(open(metadatapath, 'r'), Loader=YamlLoader) yamlinfo = yaml.load(open(metadatapath, 'r'), Loader=YamlLoader)
thisinfo.update(yamlinfo) thisinfo.update(yamlinfo)
@ -798,7 +809,7 @@ def parse_yaml_metadata(metadatapath):
return (appid, thisinfo) return (appid, thisinfo)
def parse_txt_metadata(metadatapath): def parse_txt_metadata(apps, metadatapath):
linedesc = None linedesc = None
@ -874,7 +885,7 @@ def parse_txt_metadata(metadatapath):
thisinfo['comments'].append([key, comment]) thisinfo['comments'].append([key, comment])
del curcomments[:] del curcomments[:]
appid, thisinfo = get_default_app_info_list(metadatapath) appid, thisinfo = get_default_app_info_list(apps, metadatapath)
metafile = open(metadatapath, "r") metafile = open(metadatapath, "r")
mode = 0 mode = 0

View file

@ -488,4 +488,8 @@ NsS'Current Version'
p176 p176
S'1.9.5' S'1.9.5'
p177 p177
sS'metadatapath'
p178
S'metadata/net.osmand.plus.xml'
p179
s. s.

View file

@ -2231,4 +2231,8 @@ NsS'Current Version'
p480 p480
S'3.0' S'3.0'
p481 p481
sS'metadatapath'
p482
S'metadata/org.adaway.json'
p483
s. s.

View file

@ -753,4 +753,8 @@ NsS'Current Version'
p224 p224
S'0.6.0' S'0.6.0'
p225 p225
sS'metadatapath'
p226
S'metadata/org.smssecure.smssecure.txt'
p227
s. s.

View file

@ -5485,4 +5485,8 @@ sS'Current Version'
p1456 p1456
S'1.2.6' S'1.2.6'
p1457 p1457
sS'metadatapath'
p1458
S'metadata/org.videolan.vlc.yaml'
p1459
s. s.

View file

@ -109,6 +109,44 @@ cd $WORKSPACE/docs
./gendocs.sh -o html --email admin@f-droid.org fdroid "F-Droid Server Manual" ./gendocs.sh -o html --email admin@f-droid.org fdroid "F-Droid Server Manual"
#------------------------------------------------------------------------------#
echo_header "test metadata checks"
REPOROOT=`create_test_dir`
cd $REPOROOT
touch config.py
mkdir repo
cp $WORKSPACE/tests/urzip.apk $REPOROOT/repo/
set +e
$fdroid build
if [ $? -eq 0 ]; then
echo "This should have failed because there is no metadata!"
exit 1
else
echo "testing metadata checks passed"
fi
set -e
mkdir $REPOROOT/metadata/
cp $WORKSPACE/tests/metadata/org.smssecure.smssecure.txt $REPOROOT/metadata/
$fdroid readmeta
# now make a fake duplicate
touch $REPOROOT/metadata/org.smssecure.smssecure.yaml
set +e
$fdroid readmeta
if [ $? -eq 0 ]; then
echo "This should have failed because there is a duplicate metadata file!"
exit 1
else
echo "testing duplicate metadata checks passed"
fi
set -e
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
echo_header "create a source tarball and use that to build a repo" echo_header "create a source tarball and use that to build a repo"