From cc75f2f9a434f23738ef94fa72278be5bec44cf7 Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Sat, 30 Dec 2023 15:28:14 +0800 Subject: [PATCH] feat(deploy): add index only mode in update_servergitmirrors --- fdroidserver/deploy.py | 18 +++-- tests/deploy.TestCase | 149 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 4 deletions(-) diff --git a/fdroidserver/deploy.py b/fdroidserver/deploy.py index 30909a16..ae45e676 100644 --- a/fdroidserver/deploy.py +++ b/fdroidserver/deploy.py @@ -669,10 +669,20 @@ def update_servergitmirrors(servergitmirrors, repo_section): archive_path = os.path.join(git_mirror_path, 'fdroid', 'archive') shutil.rmtree(archive_path, ignore_errors=True) - # rsync is very particular about trailing slashes - common.local_rsync( - options, repo_section.rstrip('/') + '/', git_repodir.rstrip('/') + '/' - ) + if options.index_only: + rsyncargs = ['--include', "*/"] + _get_index_includes(repo_section) + ['--exclude', '*'] + + # rsync is very particular about trailing slashes + common.local_rsync(common.get_options(), + repo_section.rstrip('/') + '/', + git_repodir.rstrip('/') + '/', + args=rsyncargs) + else: + # trailing slashes have a meaning in rsync which is not needed here, so + # make sure both paths have exactly one trailing slash + common.local_rsync(common.get_options(), + repo_section.rstrip('/') + '/', + git_repodir.rstrip('/') + '/') # use custom SSH command if identity_file specified ssh_cmd = 'ssh -oBatchMode=yes' diff --git a/tests/deploy.TestCase b/tests/deploy.TestCase index 364a566f..ceafc4ca 100755 --- a/tests/deploy.TestCase +++ b/tests/deploy.TestCase @@ -1058,6 +1058,155 @@ class DeployTest(unittest.TestCase): ) assert mock_driver.upload_object_via_stream.call_count == 1 + def test_update_servergitmirrors(self): + from libcloud.storage.drivers.s3 import S3StorageDriver + from libcloud.storage.base import Container + + # setup parameters for this test run + fdroidserver.deploy.options.identity_file = None + fdroidserver.deploy.options.no_keep_git_mirror_archive = False + fdroidserver.deploy.options.verbose = False + fdroidserver.deploy.options.quiet = True + fdroidserver.deploy.options.index_only = False + + config = {} + fdroidserver.common.fill_config_defaults(config) + fdroidserver.deploy.config = config + fdroidserver.deploy.config["servergitmirrors"] = [] + + repo_section = 'repo' + + # setup function for asserting subprocess.call invocations + call_iteration = 0 + + os.chdir(self.testdir) + repo = Path('repo') + repo.mkdir(parents=True) + fake_apk = repo / 'Sym.apk' + with fake_apk.open('w') as fp: + fp.write('not an APK, but has the right filename') + fake_index = repo / fdroidserver.deploy.INDEX_FILES[0] + with fake_index.open('w') as fp: + fp.write('not an index, but has the right filename') + + with tempfile.TemporaryDirectory() as local_copy_dir: + + def update_servergitmirrors_call(cmd): + nonlocal call_iteration + if call_iteration == 0: + self.assertListEqual( + cmd, + [ + 'rsync', + '--recursive', + '--safe-links', + '--times', + '--perms', + '--one-file-system', + '--delete', + '--chmod=Da+rx,Fa-x,a+r,u+w', + '--quiet', + 'repo/', + "git-mirror/fdroid/repo/", + ], + ) + else: + self.fail('unexpected subprocess.call invocation') + call_iteration += 1 + return 0 + + with mock.patch( + 'subprocess.call', side_effect=update_servergitmirrors_call + ): + fdroidserver.deploy.update_servergitmirrors([], repo_section) + self.assertEqual(call_iteration, 1, 'expected 1 invocations of subprocess.call') + + def test_update_servergitmirrors_in_index_only_mode(self): + from libcloud.storage.base import Container + + # setup parameters for this test run + fdroidserver.deploy.options.identity_file = None + fdroidserver.deploy.options.no_keep_git_mirror_archive = False + fdroidserver.deploy.options.verbose = False + fdroidserver.deploy.options.quiet = True + fdroidserver.deploy.options.index_only = True + + config = {} + fdroidserver.common.fill_config_defaults(config) + fdroidserver.deploy.config = config + fdroidserver.deploy.config["servergitmirrors"] = [] + + repo_section = 'repo' + + # setup function for asserting subprocess.call invocations + call_iteration = 0 + + os.chdir(self.testdir) + repo = Path('repo') + repo.mkdir(parents=True) + fake_apk = repo / 'Sym.apk' + with fake_apk.open('w') as fp: + fp.write('not an APK, but has the right filename') + fake_index = repo / fdroidserver.deploy.INDEX_FILES[0] + with fake_index.open('w') as fp: + fp.write('not an index, but has the right filename') + + with tempfile.TemporaryDirectory() as local_copy_dir: + + def update_servergitmirrors_call(cmd): + nonlocal call_iteration + if call_iteration == 0: + self.assertListEqual( + cmd, + [ + 'rsync', + '--recursive', + '--safe-links', + '--times', + '--perms', + '--one-file-system', + '--delete', + '--chmod=Da+rx,Fa-x,a+r,u+w', + '--quiet', + '--include', + "*/", + '--include', + 'repo/entry.jar', + '--include', + 'repo/entry.json', + '--include', + 'repo/entry.json.asc', + '--include', + 'repo/index-v1.jar', + '--include', + 'repo/index-v1.json', + '--include', + 'repo/index-v1.json.asc', + '--include', + 'repo/index-v2.json', + '--include', + 'repo/index-v2.json.asc', + '--include', + 'repo/index.jar', + '--include', + 'repo/index.xml', + '--exclude', + "*", + 'repo/', + "git-mirror/fdroid/repo/", + ], + ) + else: + self.fail('unexpected subprocess.call invocation') + call_iteration += 1 + return 0 + + with mock.patch( + 'subprocess.call', side_effect=update_servergitmirrors_call + ): + fdroidserver.deploy.update_servergitmirrors([], repo_section) + self.assertEqual(call_iteration, 1, 'expected 1 invocations of subprocess.call') + if __name__ == "__main__": os.chdir(os.path.dirname(__file__))