diff --git a/fdroidserver/metadata.py b/fdroidserver/metadata.py index a17e4d69..52c00d85 100644 --- a/fdroidserver/metadata.py +++ b/fdroidserver/metadata.py @@ -744,6 +744,43 @@ def parse_txt_srclib(metadatapath): return thisinfo +def parse_yml_srclib(metadatapath): + + thisinfo = {'RepoType': '', + 'Repo': '', + 'Subdir': None, + 'Prepare': None} + + if not os.path.exists(metadatapath): + warn_or_exception(_("Invalid scrlib metadata: '{file}' " + "does not exist" + .format(file=metadatapath))) + return thisinfo + + with open(metadatapath, "r", encoding="utf-8") as f: + try: + data = yaml.load(f, Loader=SafeLoader) + except yaml.error.YAMLError as e: + warn_or_exception(_("Invalid srclib metadata: could not " + "parse '{file}'" + .format(file=metadatapath))) + return thisinfo + + for key in data.keys(): + if key not in thisinfo.keys(): + warn_or_exception(_("Invalid srclib metadata: unknown key " + "'{key}' in '{file}'") + .format(key=key, file=metadatapath)) + return thisinfo + else: + if key == 'Subdir': + thisinfo[key] = str(data[key] or '').split(',') + else: + thisinfo[key] = str(data[key] or '') + + return thisinfo + + def read_srclibs(): """Read all srclib metadata. @@ -770,6 +807,10 @@ def read_srclibs(): srclibname = os.path.basename(metadatapath[:-4]) srclibs[srclibname] = parse_txt_srclib(metadatapath) + for metadatapath in sorted(glob.glob(os.path.join(srcdir, '*.yml'))): + srclibname = os.path.basename(metadatapath[:-4]) + srclibs[srclibname] = parse_yml_srclib(metadatapath) + def read_metadata(xref=True, check_vcs=[], refresh=True, sort_by_time=False): """Return a list of App instances sorted newest first diff --git a/tests/metadata.TestCase b/tests/metadata.TestCase index 0f3e3cfe..844de8ae 100755 --- a/tests/metadata.TestCase +++ b/tests/metadata.TestCase @@ -571,6 +571,7 @@ class MetadataTest(unittest.TestCase): """)) def test_parse_txt_srclib(self): + fdroidserver.metadata.warnings_action = 'error' with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with open('JSoup.txt', 'w', encoding='utf-8') as f: f.write(textwrap.dedent('''\ @@ -593,6 +594,175 @@ class MetadataTest(unittest.TestCase): 'Prepare': ''}, srclib) + def test_parse_txt_srclib_simple(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('simple.txt', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + # this should be simple + Repo Type:git + Repo:https://git.host/repo.git + ''')) + srclib = fdroidserver.metadata.parse_txt_srclib('simple.txt') + self.assertDictEqual({'Repo': 'https://git.host/repo.git', + 'RepoType': 'git', + 'Subdir': None, + 'Prepare': None}, + srclib) + + def test_parse_txt_srclib_simple_blanks(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('simple.txt', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + # this should be simple + + Repo Type:git + + Repo:https://git.host/repo.git + + Subdir: + + Prepare: + ''')) + srclib = fdroidserver.metadata.parse_txt_srclib('simple.txt') + self.assertDictEqual({'Repo': 'https://git.host/repo.git', + 'RepoType': 'git', + 'Subdir': [''], + 'Prepare': ''}, + srclib) + + def test_parse_txt_srclib_Changelog_cketti(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('Changelog-cketti.txt', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + Repo Type:git + Repo:https://github.com/cketti/ckChangeLog + + Subdir:library,ckChangeLog/src/main + Prepare:[ -f project.properties ] || echo 'source.dir=java' > ant.properties && echo -e 'android.library=true\\ntarget=android-19' > project.properties + ''')) + srclib = fdroidserver.metadata.parse_txt_srclib('Changelog-cketti.txt') + self.assertDictEqual({'Repo': 'https://github.com/cketti/ckChangeLog', + 'RepoType': 'git', + 'Subdir': ['library', 'ckChangeLog/src/main'], + 'Prepare': "[ -f project.properties ] || echo 'source.dir=java' > " + "ant.properties && echo -e " + "'android.library=true\\ntarget=android-19' > project.properties"}, + srclib) + + def test_parse_yml_srclib_unknown_key(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('test.yml', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + RepoType: git + Repo: https://example.com/test.git + Evil: I should not be here. + ''')) + with self.assertRaisesRegex(MetaDataException, + "Invalid srclib metadata: " + "unknown key 'Evil' in " + "'test.yml'"): + fdroidserver.metadata.parse_yml_srclib('test.yml') + + def test_parse_yml_srclib_does_not_exists(self): + fdroidserver.metadata.warnings_action = 'error' + with self.assertRaisesRegex(MetaDataException, + "Invalid scrlib metadata: " + "'non/existent-test-srclib.yml' " + "does not exist"): + fdroidserver.metadata.parse_yml_srclib('non/existent-test-srclib.yml') + + def test_parse_yml_srclib_simple(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('simple.yml', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + # this should be simple + RepoType: git + Repo: https://git.host/repo.git + ''')) + srclib = fdroidserver.metadata.parse_yml_srclib('simple.yml') + self.assertDictEqual({'Repo': 'https://git.host/repo.git', + 'RepoType': 'git', + 'Subdir': None, + 'Prepare': None}, + srclib) + + def test_parse_yml_srclib_simple_with_blanks(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('simple.yml', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + # this should be simple + + RepoType: git + + Repo: https://git.host/repo.git + + Subdir: + + Prepare: + ''')) + srclib = fdroidserver.metadata.parse_yml_srclib('simple.yml') + self.assertDictEqual({'Repo': 'https://git.host/repo.git', + 'RepoType': 'git', + 'Subdir': [''], + 'Prepare': ''}, + srclib) + + def test_parse_yml_srclib_Changelog_cketti(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + with open('Changelog-cketti.yml', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + RepoType: git + Repo: https://github.com/cketti/ckChangeLog + + Subdir: library,ckChangeLog/src/main + Prepare: "[ -f project.properties ] || echo 'source.dir=java' > ant.properties && echo -e 'android.library=true\\\\ntarget=android-19' > project.properties" + ''')) + srclib = fdroidserver.metadata.parse_yml_srclib('Changelog-cketti.yml') + self.assertDictEqual({'Repo': 'https://github.com/cketti/ckChangeLog', + 'RepoType': 'git', + 'Subdir': ['library', 'ckChangeLog/src/main'], + 'Prepare': "[ -f project.properties ] || echo 'source.dir=java' > " + "ant.properties && echo -e " + "'android.library=true\\ntarget=android-19' > project.properties"}, + srclib) + + def test_read_srclibs(self): + fdroidserver.metadata.warnings_action = 'error' + with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): + os.mkdir('srclibs') + with open('srclibs/simple.yml', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + RepoType: git + Repo: https://git.host/repo.git + ''')) + with open('srclibs/simple-wb.txt', 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + # this should be simple + Repo Type:git + Repo:https://git.host/repo.git + + Subdir: + Prepare: + ''')) + fdroidserver.metadata.read_srclibs() + print(fdroidserver.metadata.srclibs) + self.assertDictEqual(fdroidserver.metadata.srclibs, + {'simple-wb': {'RepoType': 'git', + 'Repo': 'https://git.host/repo.git', + 'Subdir': [''], + 'Prepare': ''}, + 'simple': {'RepoType': 'git', + 'Repo': 'https://git.host/repo.git', + 'Subdir': None, + 'Prepare': None}}) + if __name__ == "__main__": os.chdir(os.path.dirname(__file__))