mirror of
				https://github.com/f-droid/fdroidserver.git
				synced 2025-11-04 06:30:27 +03:00 
			
		
		
		
	metadata: handle empty files and dicts, and error out on non-dicts
This commit is contained in:
		
							parent
							
								
									2b81a66b79
								
							
						
					
					
						commit
						1bcd9a8489
					
				
					 2 changed files with 52 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -717,36 +717,48 @@ def parse_yaml_metadata(mf):
 | 
			
		|||
                           cause=e)
 | 
			
		||||
 | 
			
		||||
    if yamldata is None or yamldata == '':
 | 
			
		||||
        return dict()
 | 
			
		||||
        yamldata = dict()
 | 
			
		||||
    if not isinstance(yamldata, dict):
 | 
			
		||||
        _warn_or_exception(
 | 
			
		||||
            _("'{path}' has invalid format, it should be a dictionary!").format(
 | 
			
		||||
                path=mf.name
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        logging.error(_('Using blank dictionary instead of contents of {path}!').format(
 | 
			
		||||
            path=mf.name)
 | 
			
		||||
        )
 | 
			
		||||
        yamldata = dict()
 | 
			
		||||
 | 
			
		||||
    deprecated_in_yaml = ['Provides']
 | 
			
		||||
 | 
			
		||||
    if yamldata:
 | 
			
		||||
        for field in tuple(yamldata.keys()):
 | 
			
		||||
            if field not in yaml_app_fields + deprecated_in_yaml:
 | 
			
		||||
                msg = (_("Unrecognised app field '{fieldname}' in '{path}'")
 | 
			
		||||
                       .format(fieldname=field, path=mf.name))
 | 
			
		||||
                if Path(mf.name).name == '.fdroid.yml':
 | 
			
		||||
                    logging.error(msg)
 | 
			
		||||
                    del yamldata[field]
 | 
			
		||||
                else:
 | 
			
		||||
                    _warn_or_exception(msg)
 | 
			
		||||
    for field in tuple(yamldata.keys()):
 | 
			
		||||
        if field not in yaml_app_fields + deprecated_in_yaml:
 | 
			
		||||
            msg = _("Unrecognised app field '{fieldname}' in '{path}'").format(
 | 
			
		||||
                fieldname=field, path=mf.name
 | 
			
		||||
            )
 | 
			
		||||
            if Path(mf.name).name == '.fdroid.yml':
 | 
			
		||||
                logging.error(msg)
 | 
			
		||||
                del yamldata[field]
 | 
			
		||||
            else:
 | 
			
		||||
                _warn_or_exception(msg)
 | 
			
		||||
 | 
			
		||||
        for deprecated_field in deprecated_in_yaml:
 | 
			
		||||
            if deprecated_field in yamldata:
 | 
			
		||||
                logging.warning(_("Ignoring '{field}' in '{metapath}' "
 | 
			
		||||
                                  "metadata because it is deprecated.")
 | 
			
		||||
                                .format(field=deprecated_field,
 | 
			
		||||
                                        metapath=mf.name))
 | 
			
		||||
                del yamldata[deprecated_field]
 | 
			
		||||
    for deprecated_field in deprecated_in_yaml:
 | 
			
		||||
        if deprecated_field in yamldata:
 | 
			
		||||
            del yamldata[deprecated_field]
 | 
			
		||||
            logging.warning(
 | 
			
		||||
                _(
 | 
			
		||||
                    "Ignoring '{field}' in '{metapath}' "
 | 
			
		||||
                    "metadata because it is deprecated."
 | 
			
		||||
                ).format(field=deprecated_field, metapath=mf.name)
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        msg = _("Unrecognised build flag '{build_flag}' in '{path}'")
 | 
			
		||||
        for build in yamldata.get('Builds', []):
 | 
			
		||||
            for build_flag in build:
 | 
			
		||||
                if build_flag not in build_flags:
 | 
			
		||||
                    _warn_or_exception(msg.format(build_flag=build_flag, path=mf.name))
 | 
			
		||||
    msg = _("Unrecognised build flag '{build_flag}' in '{path}'")
 | 
			
		||||
    for build in yamldata.get('Builds', []):
 | 
			
		||||
        for build_flag in build:
 | 
			
		||||
            if build_flag not in build_flags:
 | 
			
		||||
                _warn_or_exception(msg.format(build_flag=build_flag, path=mf.name))
 | 
			
		||||
 | 
			
		||||
        post_parse_yaml_metadata(yamldata)
 | 
			
		||||
    post_parse_yaml_metadata(yamldata)
 | 
			
		||||
    return yamldata
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -419,6 +419,22 @@ class MetadataTest(unittest.TestCase):
 | 
			
		|||
            with self.assertRaises(MetaDataException):
 | 
			
		||||
                fdroidserver.metadata.parse_yaml_metadata(mf)
 | 
			
		||||
 | 
			
		||||
    def test_parse_yaml_metadata_continue_on_warning(self):
 | 
			
		||||
        """When errors are disabled, parsing should provide something that can work.
 | 
			
		||||
 | 
			
		||||
        When errors are disabled, then it should try to give data that
 | 
			
		||||
        lets something happen.  A zero-length file is valid for
 | 
			
		||||
        operation, it just declares a Application ID as "known" and
 | 
			
		||||
        nothing else.  This example gives a list as the base in the
 | 
			
		||||
        .yml file, which is unparsable, so it gives a warning message
 | 
			
		||||
        and carries on with a blank dict.
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        fdroidserver.metadata.warnings_action = None
 | 
			
		||||
        mf = io.StringIO('[AntiFeatures: Tracking]')
 | 
			
		||||
        mf.name = 'mock_filename.yaml'
 | 
			
		||||
        self.assertEqual(fdroidserver.metadata.parse_yaml_metadata(mf), dict())
 | 
			
		||||
 | 
			
		||||
    def test_parse_yaml_srclib_corrupt_file(self):
 | 
			
		||||
        with tempfile.TemporaryDirectory() as testdir:
 | 
			
		||||
            testdir = Path(testdir)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue