mirror of
				https://github.com/f-droid/fdroidserver.git
				synced 2025-11-04 14:30:30 +03:00 
			
		
		
		
	index-v2 'mirrors' fully settable from config
This lets mirrors: in config.yml be the same list-of-dicts format as it is in index-v2. This also includes a data format conversion to maintain the right format for the old, unchanging index v0 and v1 formats. #928 #1107
This commit is contained in:
		
							parent
							
								
									ceef07d2f2
								
							
						
					
					
						commit
						7c692a4532
					
				
					 5 changed files with 204 additions and 36 deletions
				
			
		| 
						 | 
					@ -220,6 +220,15 @@
 | 
				
			||||||
# mirrors:
 | 
					# mirrors:
 | 
				
			||||||
#   - https://foo.bar/fdroid
 | 
					#   - https://foo.bar/fdroid
 | 
				
			||||||
#   - http://foobarfoobarfoobar.onion/fdroid
 | 
					#   - http://foobarfoobarfoobar.onion/fdroid
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Or additional metadata can also be included by adding key/value pairs:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# mirrors:
 | 
				
			||||||
 | 
					#   - url: https://foo.bar/fdroid
 | 
				
			||||||
 | 
					#     countryCode: BA
 | 
				
			||||||
 | 
					#   - url: http://foobarfoobarfoobar.onion/fdroid
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# optionally specify which identity file to use when using rsync or git over SSH
 | 
					# optionally specify which identity file to use when using rsync or git over SSH
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ def make(apps, apks, repodir, archive):
 | 
				
			||||||
        repodict['address'] = archive_url
 | 
					        repodict['address'] = archive_url
 | 
				
			||||||
        if 'archive_web_base_url' in common.config:
 | 
					        if 'archive_web_base_url' in common.config:
 | 
				
			||||||
            repodict["webBaseUrl"] = common.config['archive_web_base_url']
 | 
					            repodict["webBaseUrl"] = common.config['archive_web_base_url']
 | 
				
			||||||
        urlbasepath = os.path.basename(urllib.parse.urlparse(archive_url).path)
 | 
					        repo_section = os.path.basename(urllib.parse.urlparse(archive_url).path)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        repodict['name'] = common.config['repo_name']
 | 
					        repodict['name'] = common.config['repo_name']
 | 
				
			||||||
        repodict['icon'] = common.config.get('repo_icon', common.default_config['repo_icon'])
 | 
					        repodict['icon'] = common.config.get('repo_icon', common.default_config['repo_icon'])
 | 
				
			||||||
| 
						 | 
					@ -99,27 +99,9 @@ def make(apps, apks, repodir, archive):
 | 
				
			||||||
        if 'repo_web_base_url' in common.config:
 | 
					        if 'repo_web_base_url' in common.config:
 | 
				
			||||||
            repodict["webBaseUrl"] = common.config['repo_web_base_url']
 | 
					            repodict["webBaseUrl"] = common.config['repo_web_base_url']
 | 
				
			||||||
        repodict['description'] = common.config['repo_description']
 | 
					        repodict['description'] = common.config['repo_description']
 | 
				
			||||||
        urlbasepath = os.path.basename(urllib.parse.urlparse(common.config['repo_url']).path)
 | 
					        repo_section = os.path.basename(urllib.parse.urlparse(common.config['repo_url']).path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mirrorcheckfailed = False
 | 
					    add_mirrors_to_repodict(repo_section, repodict)
 | 
				
			||||||
    mirrors = []
 | 
					 | 
				
			||||||
    for mirror in common.config.get('mirrors', []):
 | 
					 | 
				
			||||||
        base = os.path.basename(urllib.parse.urlparse(mirror).path.rstrip('/'))
 | 
					 | 
				
			||||||
        if common.config.get('nonstandardwebroot') is not True and base != 'fdroid':
 | 
					 | 
				
			||||||
            logging.error(_("mirror '%s' does not end with 'fdroid'!") % mirror)
 | 
					 | 
				
			||||||
            mirrorcheckfailed = True
 | 
					 | 
				
			||||||
        # must end with / or urljoin strips a whole path segment
 | 
					 | 
				
			||||||
        if mirror.endswith('/'):
 | 
					 | 
				
			||||||
            mirrors.append(urllib.parse.urljoin(mirror, urlbasepath))
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            mirrors.append(urllib.parse.urljoin(mirror + '/', urlbasepath))
 | 
					 | 
				
			||||||
    for mirror in common.config.get('servergitmirrors', []):
 | 
					 | 
				
			||||||
        for url in get_mirror_service_urls(mirror):
 | 
					 | 
				
			||||||
            mirrors.append(url + '/' + repodir)
 | 
					 | 
				
			||||||
    if mirrorcheckfailed:
 | 
					 | 
				
			||||||
        raise FDroidException(_("Malformed repository mirrors."))
 | 
					 | 
				
			||||||
    if mirrors:
 | 
					 | 
				
			||||||
        repodict['mirrors'] = mirrors
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    requestsdict = collections.OrderedDict()
 | 
					    requestsdict = collections.OrderedDict()
 | 
				
			||||||
    for command in ('install', 'uninstall'):
 | 
					    for command in ('install', 'uninstall'):
 | 
				
			||||||
| 
						 | 
					@ -713,16 +695,11 @@ def v2_repo(repodict, repodir, archive):
 | 
				
			||||||
        repo["icon"] = config["archive" if archive else "repo"]["icon"]
 | 
					        repo["icon"] = config["archive" if archive else "repo"]["icon"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    repo["address"] = repodict["address"]
 | 
					    repo["address"] = repodict["address"]
 | 
				
			||||||
 | 
					    if "mirrors" in repodict:
 | 
				
			||||||
 | 
					        repo["mirrors"] = repodict["mirrors"]
 | 
				
			||||||
    if "webBaseUrl" in repodict:
 | 
					    if "webBaseUrl" in repodict:
 | 
				
			||||||
        repo["webBaseUrl"] = repodict["webBaseUrl"]
 | 
					        repo["webBaseUrl"] = repodict["webBaseUrl"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if "mirrors" in repodict:
 | 
					 | 
				
			||||||
        repo["mirrors"] = [{"url": mirror} for mirror in repodict["mirrors"]]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # the first entry is traditionally the primary mirror
 | 
					 | 
				
			||||||
        if repodict['address'] not in repodict["mirrors"]:
 | 
					 | 
				
			||||||
            repo["mirrors"].insert(0, {"url": repodict['address'], "isPrimary": True})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    repo["timestamp"] = repodict["timestamp"]
 | 
					    repo["timestamp"] = repodict["timestamp"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    antiFeatures = load_locale("antiFeatures", repodir)
 | 
					    antiFeatures = load_locale("antiFeatures", repodir)
 | 
				
			||||||
| 
						 | 
					@ -878,9 +855,18 @@ def make_v1(apps, packages, repodir, repodict, requestsdict, fdroid_signing_key_
 | 
				
			||||||
        raise TypeError(repr(obj) + " is not JSON serializable")
 | 
					        raise TypeError(repr(obj) + " is not JSON serializable")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    output = collections.OrderedDict()
 | 
					    output = collections.OrderedDict()
 | 
				
			||||||
    output['repo'] = repodict
 | 
					    output['repo'] = repodict.copy()
 | 
				
			||||||
    output['requests'] = requestsdict
 | 
					    output['requests'] = requestsdict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # index-v1 only supports a list of URL strings for additional mirrors
 | 
				
			||||||
 | 
					    mirrors = []
 | 
				
			||||||
 | 
					    for mirror in repodict.get('mirrors', []):
 | 
				
			||||||
 | 
					        url = mirror['url']
 | 
				
			||||||
 | 
					        if url != repodict['address']:
 | 
				
			||||||
 | 
					            mirrors.append(mirror['url'])
 | 
				
			||||||
 | 
					    if mirrors:
 | 
				
			||||||
 | 
					        output['repo']['mirrors'] = mirrors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # establish sort order of the index
 | 
					    # establish sort order of the index
 | 
				
			||||||
    v1_sort_packages(packages, fdroid_signing_key_fingerprints)
 | 
					    v1_sort_packages(packages, fdroid_signing_key_fingerprints)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1096,8 +1082,11 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
 | 
				
			||||||
    repoel.setAttribute("version", str(repodict['version']))
 | 
					    repoel.setAttribute("version", str(repodict['version']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    addElement('description', repodict['description'], doc, repoel)
 | 
					    addElement('description', repodict['description'], doc, repoel)
 | 
				
			||||||
 | 
					    # index v0 only supports a list of URL strings for additional mirrors
 | 
				
			||||||
    for mirror in repodict.get('mirrors', []):
 | 
					    for mirror in repodict.get('mirrors', []):
 | 
				
			||||||
        addElement('mirror', mirror, doc, repoel)
 | 
					        url = mirror['url']
 | 
				
			||||||
 | 
					        if url != repodict['address']:
 | 
				
			||||||
 | 
					            addElement('mirror', url, doc, repoel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    root.appendChild(repoel)
 | 
					    root.appendChild(repoel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1407,6 +1396,83 @@ def extract_pubkey():
 | 
				
			||||||
    return hexlify(pubkey), repo_pubkey_fingerprint
 | 
					    return hexlify(pubkey), repo_pubkey_fingerprint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def add_mirrors_to_repodict(repo_section, repodict):
 | 
				
			||||||
 | 
					    """Convert config into final dict of mirror metadata for the repo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Internally and in index-v2, mirrors is a list of dicts, but it can
 | 
				
			||||||
 | 
					    be specified in the config as a string or list of strings.  Also,
 | 
				
			||||||
 | 
					    index v0 and v1 use a list of URL strings as the data structure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The first entry is traditionally the primary mirror and canonical
 | 
				
			||||||
 | 
					    URL.  'mirrors' should not be present in the index if there is
 | 
				
			||||||
 | 
					    only the canonical URL, and no other mirrors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The metadata items for each mirror entry are sorted by key to
 | 
				
			||||||
 | 
					    ensure minimum diffs in the index files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mirrors_config = common.config.get('mirrors', [])
 | 
				
			||||||
 | 
					    if type(mirrors_config) not in (list, tuple):
 | 
				
			||||||
 | 
					        mirrors_config = [mirrors_config]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mirrorcheckfailed = False
 | 
				
			||||||
 | 
					    mirrors = []
 | 
				
			||||||
 | 
					    urls = set()
 | 
				
			||||||
 | 
					    for mirror in mirrors_config:
 | 
				
			||||||
 | 
					        if isinstance(mirror, str):
 | 
				
			||||||
 | 
					            mirror = {'url': mirror}
 | 
				
			||||||
 | 
					        elif not isinstance(mirror, dict):
 | 
				
			||||||
 | 
					            logging.error(
 | 
				
			||||||
 | 
					                _('Bad entry type "{mirrortype}" in mirrors config: {mirror}').format(
 | 
				
			||||||
 | 
					                    mirrortype=type(mirror), mirror=mirror
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            mirrorcheckfailed = True
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        config_url = mirror['url']
 | 
				
			||||||
 | 
					        base = os.path.basename(urllib.parse.urlparse(config_url).path.rstrip('/'))
 | 
				
			||||||
 | 
					        if common.config.get('nonstandardwebroot') is not True and base != 'fdroid':
 | 
				
			||||||
 | 
					            logging.error(_("mirror '%s' does not end with 'fdroid'!") % config_url)
 | 
				
			||||||
 | 
					            mirrorcheckfailed = True
 | 
				
			||||||
 | 
					        # must end with / or urljoin strips a whole path segment
 | 
				
			||||||
 | 
					        if config_url.endswith('/'):
 | 
				
			||||||
 | 
					            mirror['url'] = urllib.parse.urljoin(config_url, repo_section)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            mirror['url'] = urllib.parse.urljoin(config_url + '/', repo_section)
 | 
				
			||||||
 | 
					        mirrors.append(mirror)
 | 
				
			||||||
 | 
					        if mirror['url'] in urls:
 | 
				
			||||||
 | 
					            mirrorcheckfailed = True
 | 
				
			||||||
 | 
					            logging.error(
 | 
				
			||||||
 | 
					                _('Duplicate entry "%s" in mirrors config!') % mirror['url']
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        urls.add(mirror['url'])
 | 
				
			||||||
 | 
					    for mirror in common.config.get('servergitmirrors', []):
 | 
				
			||||||
 | 
					        for url in get_mirror_service_urls(mirror):
 | 
				
			||||||
 | 
					            mirrors.append({'url': url + '/' + repo_section})
 | 
				
			||||||
 | 
					    if mirrorcheckfailed:
 | 
				
			||||||
 | 
					        raise FDroidException(_("Malformed repository mirrors."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not mirrors:
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    repodict['mirrors'] = []
 | 
				
			||||||
 | 
					    canonical_url = repodict['address']
 | 
				
			||||||
 | 
					    found_primary = False
 | 
				
			||||||
 | 
					    for mirror in mirrors:
 | 
				
			||||||
 | 
					        if canonical_url == mirror['url']:
 | 
				
			||||||
 | 
					            found_primary = True
 | 
				
			||||||
 | 
					            mirror['isPrimary'] = True
 | 
				
			||||||
 | 
					            sortedmirror = dict()
 | 
				
			||||||
 | 
					            for k in sorted(mirror.keys()):
 | 
				
			||||||
 | 
					                sortedmirror[k] = mirror[k]
 | 
				
			||||||
 | 
					            repodict['mirrors'].insert(0, sortedmirror)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            repodict['mirrors'].append(mirror)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if repodict['mirrors'] and not found_primary:
 | 
				
			||||||
 | 
					        repodict['mirrors'].insert(0, {'isPrimary': True, 'url': repodict['address']})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_mirror_service_urls(url):
 | 
					def get_mirror_service_urls(url):
 | 
				
			||||||
    """Get direct URLs from git service for use by fdroidclient.
 | 
					    """Get direct URLs from git service for use by fdroidclient.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ import optparse
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import unittest
 | 
					import unittest
 | 
				
			||||||
 | 
					import yaml
 | 
				
			||||||
import zipfile
 | 
					import zipfile
 | 
				
			||||||
from unittest.mock import patch
 | 
					from unittest.mock import patch
 | 
				
			||||||
import requests
 | 
					import requests
 | 
				
			||||||
| 
						 | 
					@ -28,6 +29,7 @@ import fdroidserver.metadata
 | 
				
			||||||
import fdroidserver.net
 | 
					import fdroidserver.net
 | 
				
			||||||
import fdroidserver.signindex
 | 
					import fdroidserver.signindex
 | 
				
			||||||
import fdroidserver.publish
 | 
					import fdroidserver.publish
 | 
				
			||||||
 | 
					from fdroidserver.exception import FDroidException
 | 
				
			||||||
from testcommon import TmpCwd, mkdtemp
 | 
					from testcommon import TmpCwd, mkdtemp
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -418,6 +420,11 @@ class IndexTest(unittest.TestCase):
 | 
				
			||||||
            'address': 'https://example.com/fdroid/repo',
 | 
					            'address': 'https://example.com/fdroid/repo',
 | 
				
			||||||
            'description': 'This is just a test',
 | 
					            'description': 'This is just a test',
 | 
				
			||||||
            'icon': 'blahblah',
 | 
					            'icon': 'blahblah',
 | 
				
			||||||
 | 
					            'mirrors': [
 | 
				
			||||||
 | 
					                {'isPrimary': True, 'url': 'https://example.com/fdroid/repo'},
 | 
				
			||||||
 | 
					                {'extra': 'data', 'url': 'http://one/fdroid/repo'},
 | 
				
			||||||
 | 
					                {'url': 'http://two/fdroid/repo'},
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
            'name': 'test',
 | 
					            'name': 'test',
 | 
				
			||||||
            'timestamp': datetime.datetime.now(),
 | 
					            'timestamp': datetime.datetime.now(),
 | 
				
			||||||
            'version': 12,
 | 
					            'version': 12,
 | 
				
			||||||
| 
						 | 
					@ -507,6 +514,26 @@ class IndexTest(unittest.TestCase):
 | 
				
			||||||
        self.assertTrue(os.path.exists(os.path.join('repo', 'index_unsigned.jar')))
 | 
					        self.assertTrue(os.path.exists(os.path.join('repo', 'index_unsigned.jar')))
 | 
				
			||||||
        self.assertFalse(os.path.exists(os.path.join('repo', 'index.jar')))
 | 
					        self.assertFalse(os.path.exists(os.path.join('repo', 'index.jar')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_make_v1_with_mirrors(self):
 | 
				
			||||||
 | 
					        os.chdir(self.testdir)
 | 
				
			||||||
 | 
					        os.mkdir('repo')
 | 
				
			||||||
 | 
					        repodict = {
 | 
				
			||||||
 | 
					            'address': 'https://example.com/fdroid/repo',
 | 
				
			||||||
 | 
					            'mirrors': [
 | 
				
			||||||
 | 
					                {'isPrimary': True, 'url': 'https://example.com/fdroid/repo'},
 | 
				
			||||||
 | 
					                {'extra': 'data', 'url': 'http://one/fdroid/repo'},
 | 
				
			||||||
 | 
					                {'url': 'http://two/fdroid/repo'},
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        fdroidserver.index.make_v1({}, [], 'repo', repodict, {}, {})
 | 
				
			||||||
 | 
					        index_v1 = Path('repo/index-v1.json')
 | 
				
			||||||
 | 
					        self.assertTrue(index_v1.exists())
 | 
				
			||||||
 | 
					        with index_v1.open() as fp:
 | 
				
			||||||
 | 
					            self.assertEqual(
 | 
				
			||||||
 | 
					                json.load(fp)['repo']['mirrors'],
 | 
				
			||||||
 | 
					                ['http://one/fdroid/repo', 'http://two/fdroid/repo'],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_github_get_mirror_service_urls(self):
 | 
					    def test_github_get_mirror_service_urls(self):
 | 
				
			||||||
        for url in [
 | 
					        for url in [
 | 
				
			||||||
            'git@github.com:foo/bar',
 | 
					            'git@github.com:foo/bar',
 | 
				
			||||||
| 
						 | 
					@ -656,16 +683,82 @@ class IndexTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_add_mirrors_to_repodict(self):
 | 
					    def test_add_mirrors_to_repodict(self):
 | 
				
			||||||
        """Test based on the contents of tests/config.py"""
 | 
					        """Test based on the contents of tests/config.py"""
 | 
				
			||||||
        repodict = dict()
 | 
					        repodict = {'address': fdroidserver.common.config['repo_url']}
 | 
				
			||||||
        fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
					        fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
				
			||||||
        self.assertEqual(
 | 
					        self.assertEqual(
 | 
				
			||||||
            repodict['mirrors'],
 | 
					            repodict['mirrors'],
 | 
				
			||||||
            [
 | 
					            [
 | 
				
			||||||
                'http://foobarfoobarfoobar.onion/fdroid/repo',
 | 
					                {'isPrimary': True, 'url': 'https://MyFirstFDroidRepo.org/fdroid/repo'},
 | 
				
			||||||
                'https://foo.bar/fdroid/repo',
 | 
					                {'url': 'http://foobarfoobarfoobar.onion/fdroid/repo'},
 | 
				
			||||||
 | 
					                {'url': 'https://foo.bar/fdroid/repo'},
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_custom_config_yml_with_mirrors(self):
 | 
				
			||||||
 | 
					        """Test based on custom contents of config.yml"""
 | 
				
			||||||
 | 
					        os.chdir(self.testdir)
 | 
				
			||||||
 | 
					        repo_url = 'https://example.com/fdroid/repo'
 | 
				
			||||||
 | 
					        with open('config.yml', 'w') as fp:
 | 
				
			||||||
 | 
					            yaml.dump({'repo_url': repo_url, 'mirrors': ['http://one/fdroid', ]}, fp)
 | 
				
			||||||
 | 
					        os.system('cat config.yml')
 | 
				
			||||||
 | 
					        fdroidserver.common.config = None
 | 
				
			||||||
 | 
					        fdroidserver.common.read_config(Options)
 | 
				
			||||||
 | 
					        repodict = {'address': fdroidserver.common.config['repo_url']}
 | 
				
			||||||
 | 
					        fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
				
			||||||
 | 
					        self.assertEqual(
 | 
				
			||||||
 | 
					            repodict['mirrors'],
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                {'url': 'https://example.com/fdroid/repo', 'isPrimary': True},
 | 
				
			||||||
 | 
					                {'url': 'http://one/fdroid/repo'},
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_no_mirrors_config(self):
 | 
				
			||||||
 | 
					        fdroidserver.common.config = dict()
 | 
				
			||||||
 | 
					        repodict = {'address': 'https://example.com/fdroid/repo'}
 | 
				
			||||||
 | 
					        fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
				
			||||||
 | 
					        self.assertFalse('mirrors' in repodict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_add_metadata_to_canonical_in_mirrors_config(self):
 | 
				
			||||||
 | 
					        """It is possible to add extra metadata to the canonical URL"""
 | 
				
			||||||
 | 
					        fdroidserver.common.config = {
 | 
				
			||||||
 | 
					            'repo_url': 'http://one/fdroid/repo',
 | 
				
			||||||
 | 
					            'mirrors': [
 | 
				
			||||||
 | 
					                {'url': 'http://one/fdroid', 'extra': 'data'},
 | 
				
			||||||
 | 
					                {'url': 'http://two/fdroid'},
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        repodict = {'address': fdroidserver.common.config['repo_url']}
 | 
				
			||||||
 | 
					        fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
				
			||||||
 | 
					        self.assertEqual(
 | 
				
			||||||
 | 
					            repodict['mirrors'],
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                {'extra': 'data', 'isPrimary': True, 'url': 'http://one/fdroid/repo'},
 | 
				
			||||||
 | 
					                {'url': 'http://two/fdroid/repo'},
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_duplicate_primary_in_mirrors_config(self):
 | 
				
			||||||
 | 
					        """There can be only one primary mirror aka canonical URL"""
 | 
				
			||||||
 | 
					        fdroidserver.common.config = {
 | 
				
			||||||
 | 
					            'repo_url': 'http://one/fdroid',
 | 
				
			||||||
 | 
					            'mirrors': [
 | 
				
			||||||
 | 
					                {'url': 'http://one/fdroid', 'countryCode': 'SA'},
 | 
				
			||||||
 | 
					                {'url': 'http://two/fdroid'},
 | 
				
			||||||
 | 
					                {'url': 'http://one/fdroid'},
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        repodict = {'address': fdroidserver.common.config['repo_url']}
 | 
				
			||||||
 | 
					        with self.assertRaises(FDroidException):
 | 
				
			||||||
 | 
					            fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_bad_type_in_mirrors_config(self):
 | 
				
			||||||
 | 
					        for i in (1, 2.3, b'asdf'):
 | 
				
			||||||
 | 
					            fdroidserver.common.config = {'mirrors': i}
 | 
				
			||||||
 | 
					            repodict = dict()
 | 
				
			||||||
 | 
					            with self.assertRaises(FDroidException):
 | 
				
			||||||
 | 
					                fdroidserver.index.add_mirrors_to_repodict('repo', repodict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    os.chdir(os.path.dirname(__file__))
 | 
					    os.chdir(os.path.dirname(__file__))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
  "version": 20002,
 | 
					  "version": 20002,
 | 
				
			||||||
  "index": {
 | 
					  "index": {
 | 
				
			||||||
    "name": "/index-v2.json",
 | 
					    "name": "/index-v2.json",
 | 
				
			||||||
    "sha256": "e791cdb7e258f0ad37a1cc6af9a62f9d75253f41348c7841524c888b2daf105c",
 | 
					    "sha256": "07fa4500736ae77fcc6434e4d70ab315b8e018aef52c2afca9f2834ddc73747d",
 | 
				
			||||||
    "size": 32946,
 | 
					    "size": 32946,
 | 
				
			||||||
    "numPackages": 10
 | 
					    "numPackages": 10
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,8 +16,8 @@
 | 
				
			||||||
    "address": "https://MyFirstFDroidRepo.org/fdroid/repo",
 | 
					    "address": "https://MyFirstFDroidRepo.org/fdroid/repo",
 | 
				
			||||||
    "mirrors": [
 | 
					    "mirrors": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "url": "https://MyFirstFDroidRepo.org/fdroid/repo",
 | 
					        "isPrimary": true,
 | 
				
			||||||
        "isPrimary": true
 | 
					        "url": "https://MyFirstFDroidRepo.org/fdroid/repo"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "url": "http://foobarfoobarfoobar.onion/fdroid/repo"
 | 
					        "url": "http://foobarfoobarfoobar.onion/fdroid/repo"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue