mirror of
				https://github.com/f-droid/fdroidserver.git
				synced 2025-11-04 14:30:30 +03:00 
			
		
		
		
	Merge branch 'purge-config.py' into 'master'
purge config.py See merge request fdroid/fdroidserver!1607
This commit is contained in:
		
						commit
						16fb0fbe91
					
				
					 24 changed files with 319 additions and 383 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -27,7 +27,6 @@ tmp/
 | 
			
		|||
/tests/repo/status
 | 
			
		||||
 | 
			
		||||
# files used in manual testing
 | 
			
		||||
/config.py
 | 
			
		||||
/config.yml
 | 
			
		||||
/tmp/
 | 
			
		||||
/logs/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,6 +274,35 @@ safety:
 | 
			
		|||
    - python3 -m safety --key "$SAFETY_API_KEY" --stage cicd scan
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# TODO tests/*/*/*.yaml are not covered
 | 
			
		||||
yamllint:
 | 
			
		||||
  image: debian:bookworm-slim
 | 
			
		||||
  rules:
 | 
			
		||||
    # once only:/changes: are ported to rules:, this could be removed:
 | 
			
		||||
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
 | 
			
		||||
      when: never
 | 
			
		||||
    - if: $CI_PIPELINE_SOURCE == "push"
 | 
			
		||||
      changes:
 | 
			
		||||
        - .gitlab-ci.yml
 | 
			
		||||
        - .safety-policy.yml
 | 
			
		||||
        - .yamllint
 | 
			
		||||
        - tests/*.yml
 | 
			
		||||
        - tests/*/*.yml
 | 
			
		||||
        - tests/*/*/.*.yml
 | 
			
		||||
  <<: *apt-template
 | 
			
		||||
  variables:
 | 
			
		||||
    LANG: C.UTF-8
 | 
			
		||||
  script:
 | 
			
		||||
    - apt-get install yamllint
 | 
			
		||||
    - yamllint
 | 
			
		||||
        .gitlab-ci.yml
 | 
			
		||||
        .safety-policy.yml
 | 
			
		||||
        .yamllint
 | 
			
		||||
        tests/*.yml
 | 
			
		||||
        tests/*/*.yml
 | 
			
		||||
        tests/*/*/.*.yml
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Run all the various linters and static analysis tools.
 | 
			
		||||
locales:
 | 
			
		||||
  image: debian:bookworm-slim
 | 
			
		||||
| 
						 | 
				
			
			@ -555,11 +584,11 @@ servergitmirrors:
 | 
			
		|||
    - ./tests/key-tricks.py
 | 
			
		||||
    - ssh-keyscan gitlab.com >> /root/.ssh/known_hosts
 | 
			
		||||
    - test -d /tmp/fdroid/repo || mkdir -p /tmp/fdroid/repo
 | 
			
		||||
    - cp tests/config.py tests/keystore.jks /tmp/fdroid/
 | 
			
		||||
    - cp tests/config.yml tests/keystore.jks /tmp/fdroid/
 | 
			
		||||
    - cp tests/repo/com.politedroid_6.apk /tmp/fdroid/repo/
 | 
			
		||||
    - cd /tmp/fdroid
 | 
			
		||||
    - touch fdroid-icon.png
 | 
			
		||||
    - printf "\nservergitmirrors = 'git@gitlab.com:fdroid/ci-test-servergitmirrors-repo.git'\n" >> config.py
 | 
			
		||||
    - printf "\nservergitmirrors\x3a 'git@gitlab.com:fdroid/ci-test-servergitmirrors-repo.git'\n" >> config.yml
 | 
			
		||||
    - $PYTHONPATH/fdroid update --verbose --create-metadata
 | 
			
		||||
    - $PYTHONPATH/fdroid deploy --verbose
 | 
			
		||||
    - export DLURL=`grep -Eo 'https://gitlab.com/fdroid/ci-test-servergitmirrors-repo[^"]+' repo/index-v1.json`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -548,7 +548,7 @@ include tests/build-tools/28.0.3/aapt-output-souch.smsbypass_9.txt
 | 
			
		|||
include tests/build-tools/generate.sh
 | 
			
		||||
include tests/check-fdroid-apk
 | 
			
		||||
include tests/com.fake.IpaApp_1000000000001.ipa
 | 
			
		||||
include tests/config.py
 | 
			
		||||
include tests/config.yml
 | 
			
		||||
include tests/config/antiFeatures.yml
 | 
			
		||||
include tests/config/categories.yml
 | 
			
		||||
include tests/config/de/antiFeatures.yml
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,6 +126,7 @@ CONFIG_NAMES = (
 | 
			
		|||
    RELEASECHANNELS_CONFIG_NAME,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CONFIG_FILE = 'config.yml'
 | 
			
		||||
 | 
			
		||||
config = None
 | 
			
		||||
options = None
 | 
			
		||||
| 
						 | 
				
			
			@ -525,14 +526,13 @@ def config_type_check(path, data):
 | 
			
		|||
def read_config():
 | 
			
		||||
    """Read the repository config.
 | 
			
		||||
 | 
			
		||||
    The config is read from config_file, which is in the current
 | 
			
		||||
    The config is read from config.yml, which is in the current
 | 
			
		||||
    directory when any of the repo management commands are used. If
 | 
			
		||||
    there is a local metadata file in the git repo, then the config is
 | 
			
		||||
    not required, just use defaults.
 | 
			
		||||
 | 
			
		||||
    config.yml is the preferred form because no code is executed when
 | 
			
		||||
    reading it.  config.py is deprecated and supported for backwards
 | 
			
		||||
    compatibility.
 | 
			
		||||
    reading it.  config.py is deprecated and no longer supported.
 | 
			
		||||
 | 
			
		||||
    config.yml requires ASCII or UTF-8 encoding because this code does
 | 
			
		||||
    not auto-detect the file's encoding.  That is left up to the YAML
 | 
			
		||||
| 
						 | 
				
			
			@ -547,33 +547,22 @@ def read_config():
 | 
			
		|||
        return config
 | 
			
		||||
 | 
			
		||||
    config = {}
 | 
			
		||||
    config_file = 'config.yml'
 | 
			
		||||
    old_config_file = 'config.py'
 | 
			
		||||
 | 
			
		||||
    if os.path.exists(config_file) and os.path.exists(old_config_file):
 | 
			
		||||
        logging.error(_("""Conflicting config files! Using {newfile}, ignoring {oldfile}!""")
 | 
			
		||||
                      .format(oldfile=old_config_file, newfile=config_file))
 | 
			
		||||
 | 
			
		||||
    if os.path.exists(config_file):
 | 
			
		||||
        logging.debug(_("Reading '{config_file}'").format(config_file=config_file))
 | 
			
		||||
        with open(config_file, encoding='utf-8') as fp:
 | 
			
		||||
    if os.path.exists(CONFIG_FILE):
 | 
			
		||||
        logging.debug(_("Reading '{config_file}'").format(config_file=CONFIG_FILE))
 | 
			
		||||
        with open(CONFIG_FILE, encoding='utf-8') as fp:
 | 
			
		||||
            config = yaml.safe_load(fp)
 | 
			
		||||
        if not config:
 | 
			
		||||
            config = {}
 | 
			
		||||
        config_type_check(config_file, config)
 | 
			
		||||
    elif os.path.exists(old_config_file):
 | 
			
		||||
        logging.warning(_("""{oldfile} is deprecated, use {newfile}""")
 | 
			
		||||
                        .format(oldfile=old_config_file, newfile=config_file))
 | 
			
		||||
        with io.open(old_config_file, "rb") as fp:
 | 
			
		||||
            code = compile(fp.read(), old_config_file, 'exec')
 | 
			
		||||
            exec(code, None, config)  # nosec TODO automatically migrate
 | 
			
		||||
        config_type_check(CONFIG_FILE, config)
 | 
			
		||||
 | 
			
		||||
        for k in ('mirrors', 'install_list', 'uninstall_list', 'serverwebroot', 'servergitroot'):
 | 
			
		||||
            if k in config:
 | 
			
		||||
                if not type(config[k]) in (str, list, tuple):
 | 
			
		||||
                    logging.warning(
 | 
			
		||||
                        _("'{field}' will be in random order! Use () or [] brackets if order is important!")
 | 
			
		||||
                        .format(field=k))
 | 
			
		||||
    old_config_file = 'config.py'
 | 
			
		||||
    if os.path.exists(old_config_file):
 | 
			
		||||
        logging.warning(
 | 
			
		||||
            _("""Ignoring deprecated {oldfile}, use {newfile}!""").format(
 | 
			
		||||
                oldfile=old_config_file, newfile=CONFIG_FILE
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    # smartcardoptions must be a list since its command line args for Popen
 | 
			
		||||
    smartcardoptions = config.get('smartcardoptions')
 | 
			
		||||
| 
						 | 
				
			
			@ -588,14 +577,13 @@ def read_config():
 | 
			
		|||
                                      '-providerArg', 'opensc-fdroid.cfg']
 | 
			
		||||
 | 
			
		||||
    if any(k in config for k in ["keystore", "keystorepass", "keypass"]):
 | 
			
		||||
        if os.path.exists(config_file):
 | 
			
		||||
            f = config_file
 | 
			
		||||
        elif os.path.exists(old_config_file):
 | 
			
		||||
            f = old_config_file
 | 
			
		||||
        st = os.stat(f)
 | 
			
		||||
        st = os.stat(CONFIG_FILE)
 | 
			
		||||
        if st.st_mode & stat.S_IRWXG or st.st_mode & stat.S_IRWXO:
 | 
			
		||||
            logging.warning(_("unsafe permissions on '{config_file}' (should be 0600)!")
 | 
			
		||||
                            .format(config_file=f))
 | 
			
		||||
            logging.warning(
 | 
			
		||||
                _("unsafe permissions on '{config_file}' (should be 0600)!").format(
 | 
			
		||||
                    config_file=CONFIG_FILE
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    fill_config_defaults(config)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4202,8 +4190,16 @@ def load_stats_fdroid_signing_key_fingerprints():
 | 
			
		|||
        return json.loads(str(f.read('publishsigkeys.json'), 'utf-8'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def write_to_config(thisconfig, key, value=None, config_file=None):
 | 
			
		||||
    """Write a key/value to the local config.yml or config.py.
 | 
			
		||||
def write_config_file(config):
 | 
			
		||||
    """Write the provided string to config.yml with the right path and encoding."""
 | 
			
		||||
    Path(CONFIG_FILE).write_text(config, encoding='utf-8')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def write_to_config(thisconfig, key, value=None):
 | 
			
		||||
    """Write a key/value to the local config.yml.
 | 
			
		||||
 | 
			
		||||
    The config.yml is defined as YAML 1.2 in UTF-8 encoding on all
 | 
			
		||||
    platforms.
 | 
			
		||||
 | 
			
		||||
    NOTE: only supports writing string variables.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4216,61 +4212,42 @@ def write_to_config(thisconfig, key, value=None, config_file=None):
 | 
			
		|||
    value
 | 
			
		||||
        optional value to be written, instead of fetched
 | 
			
		||||
        from 'thisconfig' dictionary.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    if value is None:
 | 
			
		||||
        origkey = key + '_orig'
 | 
			
		||||
        value = thisconfig[origkey] if origkey in thisconfig else thisconfig[key]
 | 
			
		||||
    if config_file:
 | 
			
		||||
        cfg = config_file
 | 
			
		||||
    elif os.path.exists('config.py') and not os.path.exists('config.yml'):
 | 
			
		||||
        cfg = 'config.py'
 | 
			
		||||
    else:
 | 
			
		||||
        cfg = 'config.yml'
 | 
			
		||||
 | 
			
		||||
    # load config file, create one if it doesn't exist
 | 
			
		||||
    if not os.path.exists(cfg):
 | 
			
		||||
        open(cfg, 'a').close()
 | 
			
		||||
        logging.info("Creating empty " + cfg)
 | 
			
		||||
    with open(cfg, 'r') as f:
 | 
			
		||||
        lines = f.readlines()
 | 
			
		||||
    if not os.path.exists(CONFIG_FILE):
 | 
			
		||||
        write_config_file('')
 | 
			
		||||
        logging.info(_("Creating empty {config_file}").format(config_file=CONFIG_FILE))
 | 
			
		||||
    with open(CONFIG_FILE) as fp:
 | 
			
		||||
        lines = fp.readlines()
 | 
			
		||||
 | 
			
		||||
    # make sure the file ends with a carraige return
 | 
			
		||||
    if len(lines) > 0:
 | 
			
		||||
        if not lines[-1].endswith('\n'):
 | 
			
		||||
            lines[-1] += '\n'
 | 
			
		||||
 | 
			
		||||
    # regex for finding and replacing python string variable
 | 
			
		||||
    # definitions/initializations
 | 
			
		||||
    if cfg.endswith('.py'):
 | 
			
		||||
        pattern = re.compile(r'^[\s#]*' + key + r'\s*=\s*"[^"]*"')
 | 
			
		||||
        repl = key + ' = "' + value + '"'
 | 
			
		||||
        pattern2 = re.compile(r'^[\s#]*' + key + r"\s*=\s*'[^']*'")
 | 
			
		||||
        repl2 = key + " = '" + value + "'"
 | 
			
		||||
    else:
 | 
			
		||||
        # assume .yml as default
 | 
			
		||||
        pattern = re.compile(r'^[\s#]*' + key + r':.*')
 | 
			
		||||
        repl = yaml.dump({key: value}, default_flow_style=False)
 | 
			
		||||
        pattern2 = pattern
 | 
			
		||||
        repl2 = repl
 | 
			
		||||
    pattern = re.compile(r'^[\s#]*' + key + r':.*\n')
 | 
			
		||||
    repl = yaml.dump({key: value})
 | 
			
		||||
 | 
			
		||||
    # If we replaced this line once, we make sure won't be a
 | 
			
		||||
    # second instance of this line for this key in the document.
 | 
			
		||||
    didRepl = False
 | 
			
		||||
    # edit config file
 | 
			
		||||
    with open(cfg, 'w') as f:
 | 
			
		||||
    with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
 | 
			
		||||
        for line in lines:
 | 
			
		||||
            if pattern.match(line) or pattern2.match(line):
 | 
			
		||||
            if pattern.match(line):
 | 
			
		||||
                if not didRepl:
 | 
			
		||||
                    line = pattern.sub(repl, line)
 | 
			
		||||
                    line = pattern2.sub(repl2, line)
 | 
			
		||||
                    f.write(line)
 | 
			
		||||
                    didRepl = True
 | 
			
		||||
            else:
 | 
			
		||||
                f.write(line)
 | 
			
		||||
        if not didRepl:
 | 
			
		||||
            f.write('\n')
 | 
			
		||||
            f.write(repl)
 | 
			
		||||
            f.write('\n')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_xml(path):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,13 +38,13 @@ def disable_in_config(key, value):
 | 
			
		|||
    """Write a key/value to the local config.yml, then comment it out."""
 | 
			
		||||
    import yaml
 | 
			
		||||
 | 
			
		||||
    with open('config.yml') as f:
 | 
			
		||||
        data = f.read()
 | 
			
		||||
    with open(common.CONFIG_FILE) as fp:
 | 
			
		||||
        data = fp.read()
 | 
			
		||||
    pattern = r'\n[\s#]*' + key + r':.*'
 | 
			
		||||
    repl = '\n#' + yaml.dump({key: value}, default_flow_style=False)
 | 
			
		||||
    data = re.sub(pattern, repl, data)
 | 
			
		||||
    with open('config.yml', 'w') as f:
 | 
			
		||||
        f.writelines(data)
 | 
			
		||||
    with open(common.CONFIG_FILE, 'w') as fp:
 | 
			
		||||
        fp.writelines(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
| 
						 | 
				
			
			@ -138,24 +138,24 @@ def main():
 | 
			
		|||
            _("Android SDK not found at {path}!").format(path=test_config['sdk_path'])
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    if not os.path.exists('config.yml') and not os.path.exists('config.py'):
 | 
			
		||||
    if not os.path.exists(common.CONFIG_FILE):
 | 
			
		||||
        # 'metadata' and 'tmp' are created in fdroid
 | 
			
		||||
        if not os.path.exists('repo'):
 | 
			
		||||
            os.mkdir('repo')
 | 
			
		||||
        example_config_yml = os.path.join(examplesdir, 'config.yml')
 | 
			
		||||
        example_config_yml = os.path.join(examplesdir, common.CONFIG_FILE)
 | 
			
		||||
        if os.path.exists(example_config_yml):
 | 
			
		||||
            shutil.copyfile(example_config_yml, 'config.yml')
 | 
			
		||||
            shutil.copyfile(example_config_yml, common.CONFIG_FILE)
 | 
			
		||||
        else:
 | 
			
		||||
            from pkg_resources import get_distribution
 | 
			
		||||
 | 
			
		||||
            versionstr = get_distribution('fdroidserver').version
 | 
			
		||||
            if not versionstr:
 | 
			
		||||
                versionstr = 'master'
 | 
			
		||||
            with open('config.yml', 'w') as fp:
 | 
			
		||||
            with open(common.CONFIG_FILE, 'w') as fp:
 | 
			
		||||
                fp.write('# see https://gitlab.com/fdroid/fdroidserver/blob/')
 | 
			
		||||
                fp.write(versionstr)
 | 
			
		||||
                fp.write('/examples/config.yml\n')
 | 
			
		||||
        os.chmod('config.yml', 0o0600)
 | 
			
		||||
                fp.write(f'/examples/{common.CONFIG_FILE}\n')
 | 
			
		||||
        os.chmod(common.CONFIG_FILE, 0o0600)
 | 
			
		||||
        # If android_home is None, test_config['sdk_path'] will be used and
 | 
			
		||||
        # "$ANDROID_HOME" may be used if the env var is set up correctly.
 | 
			
		||||
        # If android_home is not None, the path given from the command line
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -976,7 +976,7 @@ def main():
 | 
			
		|||
    paths = list()
 | 
			
		||||
    for arg in options.appid:
 | 
			
		||||
        if (
 | 
			
		||||
            arg == 'config.yml'
 | 
			
		||||
            arg == common.CONFIG_FILE
 | 
			
		||||
            or Path(arg).parent.name == 'config'
 | 
			
		||||
            or Path(arg).parent.parent.name == 'config'  # localized
 | 
			
		||||
        ):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -423,9 +423,9 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
 | 
			
		|||
            'keydname': DISTINGUISHED_NAME,
 | 
			
		||||
            'make_current_version_link': False,
 | 
			
		||||
        }
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
        with open(common.CONFIG_FILE, 'w', encoding='utf-8') as fp:
 | 
			
		||||
            yaml.dump(config, fp, default_flow_style=False)
 | 
			
		||||
        os.chmod('config.yml', 0o600)
 | 
			
		||||
        os.chmod(common.CONFIG_FILE, 0o600)
 | 
			
		||||
        config = common.read_config()
 | 
			
		||||
        common.assert_config_keystore(config)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
Summary: This should be overridden by metadata/info.guardianproject.urzip.yml
 | 
			
		||||
Builds:
 | 
			
		||||
  - versionCode: 50
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,31 +0,0 @@
 | 
			
		|||
 | 
			
		||||
# TODO convert to config.yml!
 | 
			
		||||
 | 
			
		||||
repo_url = "https://MyFirstFDroidRepo.org/fdroid/repo"
 | 
			
		||||
repo_name = "My First F-Droid Repo Demo"
 | 
			
		||||
repo_description = """This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/fdroid."""
 | 
			
		||||
 | 
			
		||||
archive_older = 3
 | 
			
		||||
archive_url = "https://f-droid.org/archive"
 | 
			
		||||
archive_name = "My First F-Droid Archive Demo"
 | 
			
		||||
archive_description = """
 | 
			
		||||
The repository of older versions of applications from the main demo repository.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
make_current_version_link = False
 | 
			
		||||
 | 
			
		||||
repo_keyalias = "sova"
 | 
			
		||||
keystore = "keystore.jks"
 | 
			
		||||
keystorepass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="
 | 
			
		||||
keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="
 | 
			
		||||
keydname = "CN=sova, OU=F-Droid"
 | 
			
		||||
 | 
			
		||||
mirrors = (
 | 
			
		||||
    'http://foobarfoobarfoobar.onion/fdroid',
 | 
			
		||||
    'https://foo.bar/fdroid',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
install_list = 'org.adaway'
 | 
			
		||||
uninstall_list = ('com.android.vending', 'com.facebook.orca', )
 | 
			
		||||
 | 
			
		||||
repo_key_sha256 = "f49af3f11efddf20dffd70f5e3117b9976674167adca280e6b1932a0601b26f6"
 | 
			
		||||
							
								
								
									
										27
									
								
								tests/config.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tests/config.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
---
 | 
			
		||||
 | 
			
		||||
repo_url: https://MyFirstFDroidRepo.org/fdroid/repo
 | 
			
		||||
repo_name: My First F-Droid Repo Demo
 | 
			
		||||
repo_description: This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/fdroid.
 | 
			
		||||
 | 
			
		||||
archive_older: 3
 | 
			
		||||
archive_url: https://f-droid.org/archive
 | 
			
		||||
archive_name: My First F-Droid Archive Demo
 | 
			
		||||
archive_description: The repository of older versions of applications from the main demo repository.
 | 
			
		||||
 | 
			
		||||
make_current_version_link: false
 | 
			
		||||
 | 
			
		||||
repo_keyalias: sova
 | 
			
		||||
keystore: keystore.jks
 | 
			
		||||
keystorepass: "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="
 | 
			
		||||
keypass: "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="
 | 
			
		||||
keydname: "CN=sova, OU=F-Droid"
 | 
			
		||||
 | 
			
		||||
mirrors:
 | 
			
		||||
  - http://foobarfoobarfoobar.onion/fdroid
 | 
			
		||||
  - https://foo.bar/fdroid
 | 
			
		||||
 | 
			
		||||
install_list: org.adaway
 | 
			
		||||
uninstall_list: ['com.android.vending', 'com.facebook.orca']
 | 
			
		||||
 | 
			
		||||
repo_key_sha256: f49af3f11efddf20dffd70f5e3117b9976674167adca280e6b1932a0601b26f6
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
Categories:
 | 
			
		||||
- tests
 | 
			
		||||
  - tests
 | 
			
		||||
Name: Duplicate Permisssions
 | 
			
		||||
Summary: 'Test app for all possible <uses-permissions>'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,10 +3,10 @@ AutoUpdateMode: None
 | 
			
		|||
Bitcoin: 1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk
 | 
			
		||||
OpenCollective: f-droid-just-testing
 | 
			
		||||
Categories:
 | 
			
		||||
- Development
 | 
			
		||||
- GuardianProject
 | 
			
		||||
- 1
 | 
			
		||||
- 2.0
 | 
			
		||||
  - Development
 | 
			
		||||
  - GuardianProject
 | 
			
		||||
  - 1
 | 
			
		||||
  - 2.0
 | 
			
		||||
CurrentVersionCode: 2147483647
 | 
			
		||||
AuthorWebSite: https://guardianproject.info
 | 
			
		||||
Description: |
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
Categories:
 | 
			
		||||
- Development
 | 
			
		||||
  - Development
 | 
			
		||||
Name: Caffeine Tile
 | 
			
		||||
Summary: Test app for extracting icons when an XML one is default
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -317,7 +317,7 @@ Builds:
 | 
			
		|||
    prebuild: sed -i '/ant/d' ../Makefile && ln -s vlc-android/$$VLC-2.2$$ ../vlc
 | 
			
		||||
    build: cd ../ && ANDROID_ABI=armeabi-v7a ./compile.sh release
 | 
			
		||||
 | 
			
		||||
#0.9.10 vercodes were off
 | 
			
		||||
  # 0.9.10 vercodes were off
 | 
			
		||||
  - versionName: 1.0.0
 | 
			
		||||
    versionCode: 10006
 | 
			
		||||
    disable: doesn't build
 | 
			
		||||
| 
						 | 
				
			
			@ -328,7 +328,7 @@ Builds:
 | 
			
		|||
    prebuild: sed -i '/ant/d' ../Makefile && ln -s vlc-android/$$VLC-2.2$$ ../vlc
 | 
			
		||||
    build: cd ../ && ANDROID_ABI=x86 ./compile.sh release
 | 
			
		||||
 | 
			
		||||
#0.9.10 vercodes were off
 | 
			
		||||
  # 0.9.10 vercodes were off
 | 
			
		||||
  - versionName: 1.0.0
 | 
			
		||||
    versionCode: 10007
 | 
			
		||||
    disable: doesn't build
 | 
			
		||||
| 
						 | 
				
			
			@ -339,7 +339,7 @@ Builds:
 | 
			
		|||
    prebuild: sed -i '/ant/d' ../Makefile && ln -s vlc-android/$$VLC-2.2$$ ../vlc
 | 
			
		||||
    build: cd ../ && ANDROID_ABI=armeabi ./compile.sh release
 | 
			
		||||
 | 
			
		||||
#0.9.10 vercodes were off
 | 
			
		||||
  # 0.9.10 vercodes were off
 | 
			
		||||
  - versionName: 1.0.0
 | 
			
		||||
    versionCode: 10008
 | 
			
		||||
    disable: doesn't build
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -593,9 +593,9 @@ class BuildTest(unittest.TestCase):
 | 
			
		|||
        os.chdir(self.testdir)
 | 
			
		||||
        sdk_path = os.path.join(self.testdir, 'android-sdk')
 | 
			
		||||
        self.create_fake_android_home(sdk_path)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
        with open(fdroidserver.common.CONFIG_FILE, 'w') as fp:
 | 
			
		||||
            yaml.dump({'sdk_path': sdk_path, 'keep_when_not_allowed': True}, fp)
 | 
			
		||||
        os.chmod('config.yml', 0o600)
 | 
			
		||||
        os.chmod(fdroidserver.common.CONFIG_FILE, 0o600)
 | 
			
		||||
        fdroidserver.build.config = fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
        os.mkdir('metadata')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
            os.makedirs(self.tmpdir)
 | 
			
		||||
        os.chdir(basedir)
 | 
			
		||||
 | 
			
		||||
        self.verbose = '-v' in sys.argv or '--verbose' in sys.argv
 | 
			
		||||
        fdroidserver.common.set_console_logging(self.verbose)
 | 
			
		||||
 | 
			
		||||
        # these are declared as None at the top of the module file
 | 
			
		||||
        fdroidserver.common.config = None
 | 
			
		||||
        fdroidserver.common.options = None
 | 
			
		||||
| 
						 | 
				
			
			@ -642,65 +645,59 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
        )
 | 
			
		||||
 | 
			
		||||
    def test_write_to_config(self):
 | 
			
		||||
        with tempfile.TemporaryDirectory() as tmpPath:
 | 
			
		||||
            cfgPath = os.path.join(tmpPath, 'config.py')
 | 
			
		||||
            with open(cfgPath, 'w') as f:
 | 
			
		||||
                f.write(
 | 
			
		||||
                    textwrap.dedent(
 | 
			
		||||
                        """\
 | 
			
		||||
        """Test that config items can be added without messing up config.yml.
 | 
			
		||||
 | 
			
		||||
        The '_orig' key are where the original string values of paths
 | 
			
		||||
        are stored.  Paths have tilde expansion and env vars replaced
 | 
			
		||||
        in fill_config_defaults().
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            textwrap.dedent(
 | 
			
		||||
                """\
 | 
			
		||||
                # abc
 | 
			
		||||
                # test: 'example value'
 | 
			
		||||
                a_path: ~/android-sdk
 | 
			
		||||
 | 
			
		||||
                # comment
 | 
			
		||||
                do_not_touch: good value
 | 
			
		||||
                a_path: "!!!"
 | 
			
		||||
 | 
			
		||||
                key: "123"    # inline"""
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        config = {'key': 111, 'a_path_orig': '~/android-sdk'}
 | 
			
		||||
        fdroidserver.common.write_to_config(config, 'key')
 | 
			
		||||
        fdroidserver.common.write_to_config(config, 'a_path')
 | 
			
		||||
        fdroidserver.common.write_to_config(config, 'test', value='test value')
 | 
			
		||||
        fdroidserver.common.write_to_config(config, 'new_key', value='new')
 | 
			
		||||
 | 
			
		||||
        with open(fdroidserver.common.CONFIG_FILE) as fp:
 | 
			
		||||
            self.assertEqual(
 | 
			
		||||
                fp.read(),
 | 
			
		||||
                textwrap.dedent(
 | 
			
		||||
                    """\
 | 
			
		||||
                    # abc
 | 
			
		||||
                    # test = 'example value'
 | 
			
		||||
                    default_me= '%%%'
 | 
			
		||||
                    test: test value
 | 
			
		||||
                    a_path: ~/android-sdk
 | 
			
		||||
 | 
			
		||||
                    # comment
 | 
			
		||||
                    do_not_touch = "good value"
 | 
			
		||||
                    default_me="!!!"
 | 
			
		||||
                    do_not_touch: good value
 | 
			
		||||
 | 
			
		||||
                    key="123"    # inline"""
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            cfg = {'key': '111', 'default_me_orig': 'orig'}
 | 
			
		||||
            fdroidserver.common.write_to_config(cfg, 'key', config_file=cfgPath)
 | 
			
		||||
            fdroidserver.common.write_to_config(cfg, 'default_me', config_file=cfgPath)
 | 
			
		||||
            fdroidserver.common.write_to_config(cfg, 'test', value='test value', config_file=cfgPath)
 | 
			
		||||
            fdroidserver.common.write_to_config(cfg, 'new_key', value='new', config_file=cfgPath)
 | 
			
		||||
 | 
			
		||||
            with open(cfgPath, 'r') as f:
 | 
			
		||||
                self.assertEqual(
 | 
			
		||||
                    f.read(),
 | 
			
		||||
                    textwrap.dedent(
 | 
			
		||||
                        """\
 | 
			
		||||
                    # abc
 | 
			
		||||
                    test = 'test value'
 | 
			
		||||
                    default_me = 'orig'
 | 
			
		||||
 | 
			
		||||
                    # comment
 | 
			
		||||
                    do_not_touch = "good value"
 | 
			
		||||
 | 
			
		||||
                    key = "111"    # inline
 | 
			
		||||
 | 
			
		||||
                    new_key = "new"
 | 
			
		||||
                    key: 111
 | 
			
		||||
                    new_key: new
 | 
			
		||||
                    """
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    def test_write_to_config_when_empty(self):
 | 
			
		||||
        with tempfile.TemporaryDirectory() as tmpPath:
 | 
			
		||||
            cfgPath = os.path.join(tmpPath, 'config.py')
 | 
			
		||||
            with open(cfgPath, 'w') as f:
 | 
			
		||||
                pass
 | 
			
		||||
            fdroidserver.common.write_to_config({}, 'key', 'val', cfgPath)
 | 
			
		||||
            with open(cfgPath, 'r') as f:
 | 
			
		||||
                self.assertEqual(
 | 
			
		||||
                    f.read(),
 | 
			
		||||
                    textwrap.dedent(
 | 
			
		||||
                        """\
 | 
			
		||||
 | 
			
		||||
                key = "val"
 | 
			
		||||
                """
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        config_yml = Path(fdroidserver.common.CONFIG_FILE)
 | 
			
		||||
        config_yml.write_text('', encoding='utf-8')
 | 
			
		||||
        fdroidserver.common.write_to_config({}, 'key', 'val')
 | 
			
		||||
        self.assertEqual(config_yml.read_text(), 'key: val\n')
 | 
			
		||||
 | 
			
		||||
    def test_apk_name_regex(self):
 | 
			
		||||
        good = [
 | 
			
		||||
| 
						 | 
				
			
			@ -1882,27 +1879,23 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
    def test_with_no_config(self):
 | 
			
		||||
        """It should set defaults if no config file is found"""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        self.assertFalse(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        self.assertFalse(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertIsNotNone(config.get('char_limits'))
 | 
			
		||||
 | 
			
		||||
    def test_with_zero_size_config(self):
 | 
			
		||||
        """It should set defaults if config file has nothing in it"""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        open('config.yml', 'w').close()
 | 
			
		||||
        self.assertTrue(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        fdroidserver.common.write_config_file('')
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertIsNotNone(config.get('char_limits'))
 | 
			
		||||
 | 
			
		||||
    def test_with_config_yml(self):
 | 
			
		||||
        """Make sure it is possible to use config.yml alone."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('apksigner: yml')
 | 
			
		||||
        self.assertTrue(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        fdroidserver.common.write_config_file('apksigner: yml')
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('yml', config.get('apksigner'))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1910,10 +1903,8 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
        """Make sure it is possible to use config.yml in UTF-8 encoding."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        teststr = '/πÇÇ现代通用字-български-عربي1/ö/yml'
 | 
			
		||||
        with open('config.yml', 'w', encoding='utf-8') as fp:
 | 
			
		||||
            fp.write('apksigner: ' + teststr)
 | 
			
		||||
        self.assertTrue(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        fdroidserver.common.write_config_file('apksigner: ' + teststr)
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual(teststr, config.get('apksigner'))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1921,10 +1912,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
        """Make sure it is possible to use config.yml Unicode encoded as ASCII."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        teststr = '/πÇÇ现代通用字-български-عربي1/ö/yml'
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
        with open(fdroidserver.common.CONFIG_FILE, 'w', encoding='utf-8') as fp:
 | 
			
		||||
            yaml.dump({'apksigner': teststr}, fp)
 | 
			
		||||
        self.assertTrue(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual(teststr, config.get('apksigner'))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1933,144 +1923,106 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with mock.patch.dict(os.environ):
 | 
			
		||||
            os.environ['SECRET'] = 'mysecretpassword'  # nosec B105
 | 
			
		||||
            with open('config.yml', 'w') as fp:
 | 
			
		||||
                fp.write("""keypass: {'env': 'SECRET'}""")
 | 
			
		||||
            self.assertTrue(os.path.exists('config.yml'))
 | 
			
		||||
            self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
            fdroidserver.common.write_config_file("""keypass: {'env': 'SECRET'}\n""")
 | 
			
		||||
            self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
            config = fdroidserver.common.read_config()
 | 
			
		||||
            self.assertEqual(os.getenv('SECRET', 'fail'), config.get('keypass'))
 | 
			
		||||
 | 
			
		||||
    def test_with_config_yml_is_dict(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        Path('config.yml').write_text('apksigner = /placeholder/path')
 | 
			
		||||
        Path(fdroidserver.common.CONFIG_FILE).write_text('apksigner = /bin/apksigner')
 | 
			
		||||
        with self.assertRaises(TypeError):
 | 
			
		||||
            fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_with_config_yml_is_not_mixed_type(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        Path('config.yml').write_text('k: v\napksigner = /placeholder/path')
 | 
			
		||||
        Path(fdroidserver.common.CONFIG_FILE).write_text('k: v\napksigner = /bin/apk')
 | 
			
		||||
        with self.assertRaises(yaml.scanner.ScannerError):
 | 
			
		||||
            fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_with_config_py(self):
 | 
			
		||||
        """Make sure it is still possible to use config.py alone."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.py', 'w') as fp:
 | 
			
		||||
            fp.write('apksigner = "py"')
 | 
			
		||||
        self.assertFalse(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertTrue(os.path.exists('config.py'))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual("py", config.get('apksigner'))
 | 
			
		||||
 | 
			
		||||
    def test_config_perm_warning(self):
 | 
			
		||||
        """Exercise the code path that issues a warning about unsafe permissions."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('keystore: foo.jks')
 | 
			
		||||
        self.assertTrue(os.path.exists(fp.name))
 | 
			
		||||
        os.chmod(fp.name, 0o666)  # nosec B103
 | 
			
		||||
        fdroidserver.common.write_config_file('keystore: foo.jks')
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        os.chmod(fdroidserver.common.CONFIG_FILE, 0o666)  # nosec B103
 | 
			
		||||
        fdroidserver.common.read_config()
 | 
			
		||||
        os.remove(fp.name)
 | 
			
		||||
        os.remove(fdroidserver.common.CONFIG_FILE)
 | 
			
		||||
        fdroidserver.common.config = None
 | 
			
		||||
 | 
			
		||||
        with open('config.py', 'w') as fp:
 | 
			
		||||
            fp.write('keystore = "foo.jks"')
 | 
			
		||||
        self.assertTrue(os.path.exists(fp.name))
 | 
			
		||||
        os.chmod(fp.name, 0o666)  # nosec B103
 | 
			
		||||
        fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_with_both_config_yml_py(self):
 | 
			
		||||
        """If config.yml and config.py are present, config.py should be ignored."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('apksigner: yml')
 | 
			
		||||
        with open('config.py', 'w') as fp:
 | 
			
		||||
            fp.write('apksigner = "py"')
 | 
			
		||||
        self.assertTrue(os.path.exists('config.yml'))
 | 
			
		||||
        self.assertTrue(os.path.exists('config.py'))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('yml', config.get('apksigner'))
 | 
			
		||||
 | 
			
		||||
    def test_config_repo_url(self):
 | 
			
		||||
        """repo_url ends in /repo, archive_url ends in /archive."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('repo_url: https://MyFirstFDroidRepo.org/fdroid/repo\n')
 | 
			
		||||
            fp.write('archive_url: https://MyFirstFDroidRepo.org/fdroid/archive')
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            textwrap.dedent(
 | 
			
		||||
                """\
 | 
			
		||||
                repo_url: https://MyFirstFDroidRepo.org/fdroid/repo
 | 
			
		||||
                archive_url: https://MyFirstFDroidRepo.org/fdroid/archive
 | 
			
		||||
                """
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('https://MyFirstFDroidRepo.org/fdroid/repo', config.get('repo_url'))
 | 
			
		||||
        self.assertEqual('https://MyFirstFDroidRepo.org/fdroid/archive', config.get('archive_url'))
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            'https://MyFirstFDroidRepo.org/fdroid/repo', config.get('repo_url')
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            'https://MyFirstFDroidRepo.org/fdroid/archive', config.get('archive_url')
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_config_repo_url_extra_slash(self):
 | 
			
		||||
        """repo_url ends in /repo, archive_url ends in /archive."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('repo_url: https://MyFirstFDroidRepo.org/fdroid/repo/')
 | 
			
		||||
        fdroidserver.common.write_config_file('repo_url: https://MyFirstFDroidRepo.org/fdroid/repo/')
 | 
			
		||||
        with self.assertRaises(FDroidException):
 | 
			
		||||
            fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_config_repo_url_not_repo(self):
 | 
			
		||||
        """repo_url ends in /repo, archive_url ends in /archive."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('repo_url: https://MyFirstFDroidRepo.org/fdroid/foo')
 | 
			
		||||
        fdroidserver.common.write_config_file('repo_url: https://MyFirstFDroidRepo.org/fdroid/foo')
 | 
			
		||||
        with self.assertRaises(FDroidException):
 | 
			
		||||
            fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_config_archive_url_extra_slash(self):
 | 
			
		||||
        """repo_url ends in /repo, archive_url ends in /archive."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('archive_url: https://MyFirstFDroidRepo.org/fdroid/archive/')
 | 
			
		||||
        fdroidserver.common.write_config_file('archive_url: https://MyFirstFDroidRepo.org/fdroid/archive/')
 | 
			
		||||
        with self.assertRaises(FDroidException):
 | 
			
		||||
            fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_config_archive_url_not_repo(self):
 | 
			
		||||
        """repo_url ends in /repo, archive_url ends in /archive."""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('archive_url: https://MyFirstFDroidRepo.org/fdroid/foo')
 | 
			
		||||
        fdroidserver.common.write_config_file('archive_url: https://MyFirstFDroidRepo.org/fdroid/foo')
 | 
			
		||||
        with self.assertRaises(FDroidException):
 | 
			
		||||
            fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_write_to_config_yml(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('apksigner: yml')
 | 
			
		||||
        self.assertTrue(os.path.exists(fp.name))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        fdroidserver.common.write_config_file('apksigner: yml')
 | 
			
		||||
        os.chmod(fdroidserver.common.CONFIG_FILE, 0o0600)
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertFalse('keypass' in config)
 | 
			
		||||
        self.assertEqual('yml', config.get('apksigner'))
 | 
			
		||||
        fdroidserver.common.write_to_config(config, 'keypass', 'mysecretpassword')
 | 
			
		||||
        with open(fp.name) as fp:
 | 
			
		||||
            print(fp.read())
 | 
			
		||||
        fdroidserver.common.config = None
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('mysecretpassword', config['keypass'])
 | 
			
		||||
 | 
			
		||||
    def test_write_to_config_py(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.py', 'w') as fp:
 | 
			
		||||
            fp.write('apksigner = "py"')
 | 
			
		||||
        self.assertTrue(os.path.exists(fp.name))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.yml'))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertFalse('keypass' in config)
 | 
			
		||||
        self.assertEqual('py', config.get('apksigner'))
 | 
			
		||||
        fdroidserver.common.write_to_config(config, 'keypass', 'mysecretpassword')
 | 
			
		||||
        fdroidserver.common.config = None
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('mysecretpassword', config['keypass'])
 | 
			
		||||
 | 
			
		||||
    def test_config_dict_with_int_keys(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write('java_paths:\n  8: /usr/lib/jvm/java-8-openjdk\n')
 | 
			
		||||
        self.assertTrue(os.path.exists(fp.name))
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            textwrap.dedent(
 | 
			
		||||
                """
 | 
			
		||||
                java_paths:
 | 
			
		||||
                  8: /usr/lib/jvm/java-8-openjdk
 | 
			
		||||
                """
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE))
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('/usr/lib/jvm/java-8-openjdk', config.get('java_paths', {}).get('8'))
 | 
			
		||||
        self.assertEqual('/usr/lib/jvm/java-8-openjdk', config['java_paths']['8'])
 | 
			
		||||
 | 
			
		||||
    @mock.patch.dict(os.environ, {'PATH': os.getenv('PATH')}, clear=True)
 | 
			
		||||
    def test_test_sdk_exists_fails_on_bad_sdk_path(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -2143,10 +2095,11 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_loading_config_buildserver_yml(self):
 | 
			
		||||
        """Smoke check to make sure this file is properly parsed"""
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        shutil.copy(os.path.join(basedir, '..', 'buildserver', 'config.buildserver.yml'),
 | 
			
		||||
                    'config.yml')
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        shutil.copy(
 | 
			
		||||
            os.path.join(basedir, '..', 'buildserver', 'config.buildserver.yml'),
 | 
			
		||||
            fdroidserver.common.CONFIG_FILE,
 | 
			
		||||
        )
 | 
			
		||||
        fdroidserver.common.read_config()
 | 
			
		||||
 | 
			
		||||
    def test_setup_status_output(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -2653,7 +2606,7 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_get_apksigner_smartcardoptions(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
        with open(fdroidserver.common.CONFIG_FILE, 'w', encoding='utf-8') as fp:
 | 
			
		||||
            d = {
 | 
			
		||||
                'smartcardoptions': '-storetype PKCS11'
 | 
			
		||||
                ' -providerName SunPKCS11-OpenSC'
 | 
			
		||||
| 
						 | 
				
			
			@ -2681,10 +2634,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_get_smartcardoptions_list(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write(
 | 
			
		||||
                textwrap.dedent(
 | 
			
		||||
                    """
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            textwrap.dedent(
 | 
			
		||||
                """
 | 
			
		||||
                    smartcardoptions:
 | 
			
		||||
                      - -storetype
 | 
			
		||||
                      -  PKCS11
 | 
			
		||||
| 
						 | 
				
			
			@ -2694,9 +2646,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
                      -  sun.security.pkcs11.SunPKCS11
 | 
			
		||||
                      - -providerArg
 | 
			
		||||
                      -  opensc-fdroid.cfg
 | 
			
		||||
                    """
 | 
			
		||||
                )
 | 
			
		||||
                """
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        fdroidserver.common.config = config
 | 
			
		||||
        self.assertTrue(isinstance(config['smartcardoptions'], list))
 | 
			
		||||
| 
						 | 
				
			
			@ -2716,17 +2668,16 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_get_smartcardoptions_spaces(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
            fp.write(
 | 
			
		||||
                textwrap.dedent(
 | 
			
		||||
                    """smartcardoptions: |
 | 
			
		||||
                         -storetype      PKCS11
 | 
			
		||||
                         -providerClass  sun.security.pkcs11.SunPKCS11
 | 
			
		||||
                         -providerArg    /etc/pkcs11_java.cfg
 | 
			
		||||
 | 
			
		||||
                    """
 | 
			
		||||
                )
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            textwrap.dedent(
 | 
			
		||||
                """
 | 
			
		||||
                smartcardoptions: |
 | 
			
		||||
                  -storetype      PKCS11
 | 
			
		||||
                  -providerClass  sun.security.pkcs11.SunPKCS11
 | 
			
		||||
                  -providerArg    /etc/pkcs11_java.cfg
 | 
			
		||||
                """
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        fdroidserver.common.config = config
 | 
			
		||||
        self.assertTrue(isinstance(config['smartcardoptions'], list))
 | 
			
		||||
| 
						 | 
				
			
			@ -2742,35 +2693,6 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
            config['smartcardoptions'],
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_get_smartcardoptions_config_py(self):
 | 
			
		||||
        os.chdir(self.tmpdir)
 | 
			
		||||
        with open('config.py', 'w') as fp:
 | 
			
		||||
            fp.write(
 | 
			
		||||
                textwrap.dedent(
 | 
			
		||||
                    """
 | 
			
		||||
                    smartcardoptions = '''
 | 
			
		||||
                    \t-storetype\tPKCS11
 | 
			
		||||
                    \t-providerClass\tsun.security.pkcs11.SunPKCS11
 | 
			
		||||
                    \t-providerArg\t/etc/pkcs11_java.cfg
 | 
			
		||||
 | 
			
		||||
                     '''
 | 
			
		||||
                    """
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        fdroidserver.common.config = config
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            [
 | 
			
		||||
                '-storetype',
 | 
			
		||||
                'PKCS11',
 | 
			
		||||
                '-providerClass',
 | 
			
		||||
                'sun.security.pkcs11.SunPKCS11',
 | 
			
		||||
                '-providerArg',
 | 
			
		||||
                '/etc/pkcs11_java.cfg',
 | 
			
		||||
            ],
 | 
			
		||||
            config['smartcardoptions'],
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_load_localized_config(self):
 | 
			
		||||
        """It should load"""
 | 
			
		||||
        antiFeatures = fdroidserver.common.load_localized_config(
 | 
			
		||||
| 
						 | 
				
			
			@ -2877,7 +2799,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_config_serverwebroot_str(self):
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        Path('config.yml').write_text("""serverwebroot: 'foo@example.com:/var/www'""")
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            """serverwebroot: 'foo@example.com:/var/www'"""
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            [{'url': 'foo@example.com:/var/www/'}],
 | 
			
		||||
            fdroidserver.common.read_config()['serverwebroot'],
 | 
			
		||||
| 
						 | 
				
			
			@ -2885,7 +2809,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_config_serverwebroot_list(self):
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        Path('config.yml').write_text("""serverwebroot:\n  - foo@example.com:/var/www""")
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            """serverwebroot:\n  - foo@example.com:/var/www"""
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            [{'url': 'foo@example.com:/var/www/'}],
 | 
			
		||||
            fdroidserver.common.read_config()['serverwebroot'],
 | 
			
		||||
| 
						 | 
				
			
			@ -2893,7 +2819,9 @@ class CommonTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_config_serverwebroot_dict(self):
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        Path('config.yml').write_text("""serverwebroot:\n  - url: 'foo@example.com:/var/www'""")
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            """serverwebroot:\n  - url: 'foo@example.com:/var/www'"""
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            [{'url': 'foo@example.com:/var/www/'}],
 | 
			
		||||
            fdroidserver.common.read_config()['serverwebroot'],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,8 +38,8 @@ class IndexTest(unittest.TestCase):
 | 
			
		|||
        cls.index_v1_jar = basedir / 'repo' / 'index-v1.jar'
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        (basedir / 'config.py').chmod(0o600)
 | 
			
		||||
        os.chdir(basedir)  # so read_config() can find config.py
 | 
			
		||||
        (basedir / common.CONFIG_FILE).chmod(0o600)
 | 
			
		||||
        os.chdir(basedir)  # so read_config() can find config.yml
 | 
			
		||||
 | 
			
		||||
        common.config = None
 | 
			
		||||
        common.options = Options
 | 
			
		||||
| 
						 | 
				
			
			@ -380,8 +380,7 @@ class IndexTest(unittest.TestCase):
 | 
			
		|||
            with zipfile.ZipFile(jarfile, 'w', zipfile.ZIP_DEFLATED) as jar:
 | 
			
		||||
                jar.writestr('publishsigkeys.json', json.dumps(sigkeyfps))
 | 
			
		||||
            publish.sign_sig_key_fingerprint_list(jarfile)
 | 
			
		||||
            with open('config.py', 'w'):
 | 
			
		||||
                pass
 | 
			
		||||
            common.write_config_file('')
 | 
			
		||||
 | 
			
		||||
            index.v1_sort_packages(
 | 
			
		||||
                i, common.load_stats_fdroid_signing_key_fingerprints()
 | 
			
		||||
| 
						 | 
				
			
			@ -701,7 +700,7 @@ class IndexTest(unittest.TestCase):
 | 
			
		|||
        )
 | 
			
		||||
 | 
			
		||||
    def test_add_mirrors_to_repodict(self):
 | 
			
		||||
        """Test based on the contents of tests/config.py"""
 | 
			
		||||
        """Test based on the contents of tests/config.yml"""
 | 
			
		||||
        repodict = {'address': common.config['repo_url']}
 | 
			
		||||
        index.add_mirrors_to_repodict('repo', repodict)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
| 
						 | 
				
			
			@ -718,7 +717,7 @@ class IndexTest(unittest.TestCase):
 | 
			
		|||
        os.chdir(self.testdir)
 | 
			
		||||
        repo_url = 'https://example.com/fdroid/repo'
 | 
			
		||||
        c = {'repo_url': repo_url, 'mirrors': ['http://one/fdroid']}
 | 
			
		||||
        with open('config.yml', 'w') as fp:
 | 
			
		||||
        with open(common.CONFIG_FILE, 'w', encoding='utf-8') as fp:
 | 
			
		||||
            yaml.dump(c, fp)
 | 
			
		||||
        common.config = None
 | 
			
		||||
        common.read_config()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,12 +28,13 @@ class InitTest(unittest.TestCase):
 | 
			
		|||
        self._td.cleanup()
 | 
			
		||||
 | 
			
		||||
    def test_disable_in_config(self):
 | 
			
		||||
        configfile = pathlib.Path('config.yml')
 | 
			
		||||
        configfile.write_text('keystore: NONE\nkeypass: mysupersecrets\n')
 | 
			
		||||
        test = 'mysupersecrets'
 | 
			
		||||
        configfile = pathlib.Path(fdroidserver.common.CONFIG_FILE)
 | 
			
		||||
        configfile.write_text(f'keystore: NONE\nkeypass: {test}\n', encoding='utf-8')
 | 
			
		||||
        configfile.chmod(0o600)
 | 
			
		||||
        config = fdroidserver.common.read_config()
 | 
			
		||||
        self.assertEqual('NONE', config['keystore'])
 | 
			
		||||
        self.assertEqual('mysupersecrets', config['keypass'])
 | 
			
		||||
        self.assertEqual(test, config['keypass'])
 | 
			
		||||
        fdroidserver.init.disable_in_config('keypass', 'comment')
 | 
			
		||||
        self.assertIn('#keypass:', configfile.read_text())
 | 
			
		||||
        fdroidserver.common.config = None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
            + ["init", "--keystore", keystore_path, "--repo-keyalias", "sova"]
 | 
			
		||||
        )
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "keystorepass": "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=",
 | 
			
		||||
                "keypass": "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=",
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +160,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        shutil.copy(FILES / "keystore.jks", "keystore.jks")
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore("keystore.jks")
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "make_current_version_link": True,
 | 
			
		||||
                "keydname": "CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US",
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +193,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
    def test_utf8_metadata(self):
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "repo_description": "获取已安装在您的设备上的应用的",
 | 
			
		||||
                "mirrors": ["https://foo.bar/fdroid", "http://secret.onion/fdroid"],
 | 
			
		||||
| 
						 | 
				
			
			@ -247,7 +247,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        shutil.copytree(FILES / "gnupghome", gnupghome)
 | 
			
		||||
        os.chmod(gnupghome, 0o700)
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "install_list": "org.adaway",
 | 
			
		||||
                "uninstall_list": ["com.android.vending", "com.facebook.orca"],
 | 
			
		||||
| 
						 | 
				
			
			@ -334,7 +334,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
            FILES.glob("repo/obb.main.twoversions_110161[357].apk"),
 | 
			
		||||
        ):
 | 
			
		||||
            shutil.copy(f, "repo")
 | 
			
		||||
        self.update_yaml("config.yml", {"archive_older": 3})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"archive_older": 3})
 | 
			
		||||
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update", "--pretty", "--nosign"])
 | 
			
		||||
        with open("archive/index.xml") as f:
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +356,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        shutil.copy(FILES / "metadata/com.politedroid.yml", "metadata")
 | 
			
		||||
        for f in FILES.glob("repo/com.politedroid_[0-9].apk"):
 | 
			
		||||
            shutil.copy(f, "repo")
 | 
			
		||||
        self.update_yaml("config.yml", {"archive_older": 3})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"archive_older": 3})
 | 
			
		||||
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update", "--pretty", "--nosign"])
 | 
			
		||||
        repo = Path("repo/index.xml").read_text()
 | 
			
		||||
| 
						 | 
				
			
			@ -456,7 +456,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        self.remove_lines("metadata/com.politedroid.yml", ["ArchivePolicy:"])
 | 
			
		||||
        for f in FILES.glob("repo/com.politedroid_[0-9].apk"):
 | 
			
		||||
            shutil.copy(f, "repo")
 | 
			
		||||
        self.update_yaml("config.yml", {"archive_older": 3})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"archive_older": 3})
 | 
			
		||||
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update", "--pretty", "--nosign"])
 | 
			
		||||
        repo = Path("repo/index.xml").read_text()
 | 
			
		||||
| 
						 | 
				
			
			@ -474,7 +474,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        self.assertIn("com.politedroid_3.apk", archive)
 | 
			
		||||
        self.assertTrue(Path("archive/com.politedroid_3.apk").is_file())
 | 
			
		||||
 | 
			
		||||
        self.update_yaml("config.yml", {"archive_older": 1})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"archive_older": 1})
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update", "--pretty", "--nosign"])
 | 
			
		||||
        repo = Path("repo/index.xml").read_text()
 | 
			
		||||
        repo_cnt = sum(1 for line in repo.splitlines() if "<package>" in line)
 | 
			
		||||
| 
						 | 
				
			
			@ -555,7 +555,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
    def test_allowing_disabled_signatures_in_repo_and_archive(self):
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml", {"allow_disabled_algorithms": True, "archive_older": 3}
 | 
			
		||||
            common.CONFIG_FILE, {"allow_disabled_algorithms": True, "archive_older": 3}
 | 
			
		||||
        )
 | 
			
		||||
        Path("metadata").mkdir()
 | 
			
		||||
        shutil.copy(FILES / "metadata/com.politedroid.yml", "metadata")
 | 
			
		||||
| 
						 | 
				
			
			@ -650,7 +650,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
            self.assertTrue(Path("archive/urzip-badsig.apk").is_file())
 | 
			
		||||
 | 
			
		||||
        # test unarchiving when disabled_algorithms are allowed again
 | 
			
		||||
        self.update_yaml("config.yml", {"allow_disabled_algorithms": True})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"allow_disabled_algorithms": True})
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update", "--pretty", "--nosign"])
 | 
			
		||||
        with open("archive/index.xml") as f:
 | 
			
		||||
            archive_cnt = sum(1 for line in f if "<package>" in line)
 | 
			
		||||
| 
						 | 
				
			
			@ -689,7 +689,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
    def test_rename_apks_with_fdroid_update_rename_apks_opt_nosign_opt_for_speed(self):
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "keydname": "CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US"
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -744,7 +744,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_for_added_date_being_set_correctly_for_repo_and_archive(self):
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml("config.yml", {"archive_older": 3})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"archive_older": 3})
 | 
			
		||||
        Path("metadata").mkdir()
 | 
			
		||||
        Path("archive").mkdir()
 | 
			
		||||
        Path("stats").mkdir()
 | 
			
		||||
| 
						 | 
				
			
			@ -803,12 +803,14 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        )
 | 
			
		||||
        # fake that no JDKs are available
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml", {"categories": ["Internet"], "java_paths": {}}, replace=True
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {"categories": ["Internet"], "java_paths": {}},
 | 
			
		||||
            replace=True,
 | 
			
		||||
        )
 | 
			
		||||
        local_copy_dir = self.testdir / "local_copy_dir/fdroid"
 | 
			
		||||
        (local_copy_dir / "repo").mkdir(parents=True)
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml", {"local_copy_dir": str(local_copy_dir.resolve())}
 | 
			
		||||
            common.CONFIG_FILE, {"local_copy_dir": str(local_copy_dir.resolve())}
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        subprocess.run(self.fdroid_cmd + ["checkupdates", "--allow-dirty"])
 | 
			
		||||
| 
						 | 
				
			
			@ -879,7 +881,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        new_tmp_repo.mkdir()
 | 
			
		||||
        os.chdir(new_tmp_repo)
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml("config.yml", {"sync_from_local_copy_dir": True})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"sync_from_local_copy_dir": True})
 | 
			
		||||
        self.assert_run(
 | 
			
		||||
            self.fdroid_cmd + ["deploy", "--local-copy-dir", local_copy_dir]
 | 
			
		||||
        )
 | 
			
		||||
| 
						 | 
				
			
			@ -946,7 +948,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
        # the value set in --android-home should override $ANDROID_HOME
 | 
			
		||||
        self.assertIn(str(fake_android_home), Path("config.yml").read_text())
 | 
			
		||||
        self.assertIn(str(fake_android_home), Path(common.CONFIG_FILE).read_text())
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(
 | 
			
		||||
        "ANDROID_HOME" in os.environ, "runs only with ANDROID_HOME set"
 | 
			
		||||
| 
						 | 
				
			
			@ -1097,7 +1099,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        # now set up fake, non-working keystore setup
 | 
			
		||||
        Path("keystore.p12").touch()
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "keystore": "keystore.p12",
 | 
			
		||||
                "repo_keyalias": "foo",
 | 
			
		||||
| 
						 | 
				
			
			@ -1115,7 +1117,9 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        shutil.copytree(FILES / "repo", "repo", dirs_exist_ok=True)
 | 
			
		||||
        shutil.copytree(FILES / "metadata", "metadata")
 | 
			
		||||
        git_remote = self.testdir / "git_remote"
 | 
			
		||||
        self.update_yaml("config.yml", {"binary_transparency_remote": str(git_remote)})
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            common.CONFIG_FILE, {"binary_transparency_remote": str(git_remote)}
 | 
			
		||||
        )
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update", "--verbose"])
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["deploy", "--verbose"])
 | 
			
		||||
        self.assertIn("<application id=", Path("repo/index.xml").read_text())
 | 
			
		||||
| 
						 | 
				
			
			@ -1146,7 +1150,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        self.assertTrue(apkcache.stat().st_size > 0)
 | 
			
		||||
 | 
			
		||||
        # now set fake repo_keyalias
 | 
			
		||||
        self.update_yaml("config.yml", {"repo_keyalias": "fake"})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"repo_keyalias": "fake"})
 | 
			
		||||
        # this should fail because this repo has a bad repo_keyalias
 | 
			
		||||
        self.assert_run_fail(self.fdroid_cmd + ["update"])
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1179,7 +1183,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {"archive_older": 3, "servergitmirrors": str(server_git_mirror)},
 | 
			
		||||
        )
 | 
			
		||||
        for f in FILES.glob("repo/com.politedroid_[345].apk"):
 | 
			
		||||
| 
						 | 
				
			
			@ -1226,7 +1230,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
            f.stat().st_size for f in (git_mirror / ".git").glob("**/*") if f.is_file()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.update_yaml("config.yml", {"git_mirror_size_limit": "60kb"})
 | 
			
		||||
        self.update_yaml(common.CONFIG_FILE, {"git_mirror_size_limit": "60kb"})
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["update"])
 | 
			
		||||
        self.assert_run(self.fdroid_cmd + ["deploy"])
 | 
			
		||||
        self.assertTrue(Path("archive/com.politedroid_3.apk").is_file())
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,7 +1278,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        Path("unsigned").mkdir()
 | 
			
		||||
        shutil.copy(FILES / "urzip-release-unsigned.apk", "unsigned")
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "archive_older": 3,
 | 
			
		||||
                "mirrors": [
 | 
			
		||||
| 
						 | 
				
			
			@ -1312,7 +1316,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
        )
 | 
			
		||||
        os.chdir(online_root)
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "local_copy_dir": str(local_copy_dir),
 | 
			
		||||
                "sync_from_local_copy_dir": True,
 | 
			
		||||
| 
						 | 
				
			
			@ -1344,7 +1348,7 @@ class IntegrationTest(unittest.TestCase):
 | 
			
		|||
    def test_extracting_and_publishing_with_developer_signature(self):
 | 
			
		||||
        self.fdroid_init_with_prebuilt_keystore()
 | 
			
		||||
        self.update_yaml(
 | 
			
		||||
            "config.yml",
 | 
			
		||||
            common.CONFIG_FILE,
 | 
			
		||||
            {
 | 
			
		||||
                "keydname": "CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US"
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -345,7 +345,7 @@ class LintTest(unittest.TestCase):
 | 
			
		|||
    def test_check_categories_from_config_yml(self):
 | 
			
		||||
        """In config.yml, categories is a list."""
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        Path('config.yml').write_text('categories: [foo, bar]\n')
 | 
			
		||||
        fdroidserver.common.write_config_file('categories: [foo, bar]\n')
 | 
			
		||||
        fdroidserver.lint.config = fdroidserver.common.read_config()
 | 
			
		||||
        fdroidserver.lint.load_categories_config()
 | 
			
		||||
        self.assertEqual(fdroidserver.lint.CATEGORIES_KEYS, ['foo', 'bar'])
 | 
			
		||||
| 
						 | 
				
			
			@ -434,9 +434,11 @@ class LintTest(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_lint_invalid_config_keys(self):
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        Path('config').mkdir()
 | 
			
		||||
        Path('config/config.yml').write_text('repo:\n  invalid_key: test\n')
 | 
			
		||||
        self.assertFalse(fdroidserver.lint.lint_config('config/config.yml'))
 | 
			
		||||
        os.mkdir('config')
 | 
			
		||||
        config_yml = fdroidserver.common.CONFIG_FILE
 | 
			
		||||
        with open(f'config/{config_yml}', 'w', encoding='utf-8') as fp:
 | 
			
		||||
            fp.write('repo:\n  invalid_key: test\n')
 | 
			
		||||
        self.assertFalse(fdroidserver.lint.lint_config(f'config/{config_yml}'))
 | 
			
		||||
 | 
			
		||||
    def test_lint_invalid_localized_config_keys(self):
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
| 
						 | 
				
			
			@ -534,7 +536,7 @@ class LintAntiFeaturesTest(unittest.TestCase):
 | 
			
		|||
class ConfigYmlTest(LintTest):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super().setUp()
 | 
			
		||||
        self.config_yml = Path(self.testdir) / 'config.yml'
 | 
			
		||||
        self.config_yml = Path(self.testdir) / fdroidserver.common.CONFIG_FILE
 | 
			
		||||
 | 
			
		||||
    def test_config_yml_int(self):
 | 
			
		||||
        self.config_yml.write_text('repo_maxage: 1\n')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,7 +250,6 @@ class NightlyTest(unittest.TestCase):
 | 
			
		|||
                        raise
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(called, [['ssh', '-Tvi'], ['fdroid', 'deploy']])
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        git_url = 'git@github.com:f-droid/test-nightly'
 | 
			
		||||
        mirror_url = index.get_mirror_service_urls({"url": git_url})[0]
 | 
			
		||||
        expected = {
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +268,7 @@ class NightlyTest(unittest.TestCase):
 | 
			
		|||
            'repo_url': mirror_url + '/repo',
 | 
			
		||||
            'servergitmirrors': [{"url": git_url}],
 | 
			
		||||
        }
 | 
			
		||||
        with open('config.yml') as fp:
 | 
			
		||||
        with open(common.CONFIG_FILE) as fp:
 | 
			
		||||
            config = yaml.safe_load(fp)
 | 
			
		||||
            # .ssh is random tmpdir set in nightly.py, so test basename only
 | 
			
		||||
            self.assertEqual(
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +323,6 @@ class NightlyTest(unittest.TestCase):
 | 
			
		|||
                        raise
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(called, [['ssh', '-Tvi'], ['fdroid', 'deploy']])
 | 
			
		||||
        self.assertFalse(os.path.exists('config.py'))
 | 
			
		||||
        expected = {
 | 
			
		||||
            'archive_description': 'Old nightly builds that have been archived.',
 | 
			
		||||
            'archive_name': 'fdroid/test-nightly archive',
 | 
			
		||||
| 
						 | 
				
			
			@ -341,7 +339,7 @@ class NightlyTest(unittest.TestCase):
 | 
			
		|||
            'repo_url': 'https://gitlab.com/fdroid/test-nightly/-/raw/master/fdroid/repo',
 | 
			
		||||
            'servergitmirrors': [{"url": 'git@gitlab.com:fdroid/test-nightly'}],
 | 
			
		||||
        }
 | 
			
		||||
        with open('config.yml') as fp:
 | 
			
		||||
        with open(common.CONFIG_FILE) as fp:
 | 
			
		||||
            config = yaml.safe_load(fp)
 | 
			
		||||
            # .ssh is random tmpdir set in nightly.py, so test basename only
 | 
			
		||||
            self.assertEqual(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
import json
 | 
			
		||||
import os
 | 
			
		||||
import pathlib
 | 
			
		||||
import ruamel.yaml
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
import unittest
 | 
			
		||||
| 
						 | 
				
			
			@ -94,8 +95,7 @@ class PublishTest(unittest.TestCase):
 | 
			
		|||
        ]
 | 
			
		||||
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        with open('config.py', 'w') as f:
 | 
			
		||||
            pass
 | 
			
		||||
        common.write_config_file('')
 | 
			
		||||
 | 
			
		||||
        publish.store_stats_fdroid_signing_key_fingerprints(appids, indent=2)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -116,11 +116,13 @@ class PublishTest(unittest.TestCase):
 | 
			
		|||
        }
 | 
			
		||||
        self.assertEqual(expected, common.load_stats_fdroid_signing_key_fingerprints())
 | 
			
		||||
 | 
			
		||||
        with open('config.py', 'r') as f:
 | 
			
		||||
            self.assertEqual(
 | 
			
		||||
                '\nrepo_key_sha256 = "c58460800c7b250a619c30c13b07b7359a43e5af71a4352d86c58ae18c9f6d41"\n',
 | 
			
		||||
                f.read(),
 | 
			
		||||
            )
 | 
			
		||||
        yaml = ruamel.yaml.YAML(typ='safe')
 | 
			
		||||
        with open(common.CONFIG_FILE) as fp:
 | 
			
		||||
            config = yaml.load(fp)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            'c58460800c7b250a619c30c13b07b7359a43e5af71a4352d86c58ae18c9f6d41',
 | 
			
		||||
            config['repo_key_sha256'],
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_store_and_load_fdroid_signing_key_fingerprints_with_missmatch(self):
 | 
			
		||||
        common.config = {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -800,7 +800,7 @@ class Test_ScannerTool(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_refresh_from_config(self):
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        pathlib.Path('config.yml').write_text('refresh_scanner: true')
 | 
			
		||||
        fdroidserver.common.write_config_file('refresh_scanner: true\n')
 | 
			
		||||
        with mock.patch('fdroidserver.scanner.ScannerTool.refresh') as refresh:
 | 
			
		||||
            fdroidserver.scanner.ScannerTool()
 | 
			
		||||
            refresh.assert_called_once()
 | 
			
		||||
| 
						 | 
				
			
			@ -809,7 +809,7 @@ class Test_ScannerTool(unittest.TestCase):
 | 
			
		|||
        fdroidserver.common.options = mock.Mock()
 | 
			
		||||
        fdroidserver.common.options.refresh_scanner = True
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        pathlib.Path('config.yml').write_text('refresh_scanner: false')
 | 
			
		||||
        fdroidserver.common.write_config_file('refresh_scanner: false\n')
 | 
			
		||||
        with mock.patch('fdroidserver.scanner.ScannerTool.refresh') as refresh:
 | 
			
		||||
            fdroidserver.scanner.ScannerTool()
 | 
			
		||||
            refresh.assert_called_once()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1787,7 +1787,9 @@ class UpdateTest(unittest.TestCase):
 | 
			
		|||
    def test_categories_txt_is_removed_by_delete_unknown(self):
 | 
			
		||||
        """categories.txt used to be a part of this system, now its nothing."""
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
        Path('config.yml').write_text('repo_pubkey: ffffffffffffffffffffffffffffffffffffffff')
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff\n'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        categories_txt = Path('repo/categories.txt')
 | 
			
		||||
        categories_txt.parent.mkdir()
 | 
			
		||||
| 
						 | 
				
			
			@ -1803,8 +1805,8 @@ class UpdateTest(unittest.TestCase):
 | 
			
		|||
        os.chdir(self.testdir)
 | 
			
		||||
        os.mkdir('metadata')
 | 
			
		||||
        os.mkdir('repo')
 | 
			
		||||
        Path('config.yml').write_text(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff'
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff\n'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        testapk = os.path.join('repo', 'com.politedroid_6.apk')
 | 
			
		||||
| 
						 | 
				
			
			@ -1822,8 +1824,8 @@ class UpdateTest(unittest.TestCase):
 | 
			
		|||
        os.chdir(self.testdir)
 | 
			
		||||
        os.mkdir('metadata')
 | 
			
		||||
        os.mkdir('repo')
 | 
			
		||||
        Path('config.yml').write_text(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff'
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff\n'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        testapk = os.path.join('repo', 'com.politedroid_6.apk')
 | 
			
		||||
| 
						 | 
				
			
			@ -1844,8 +1846,8 @@ class UpdateTest(unittest.TestCase):
 | 
			
		|||
        os.chdir(self.testdir)
 | 
			
		||||
        os.mkdir('metadata')
 | 
			
		||||
        os.mkdir('repo')
 | 
			
		||||
        Path('config.yml').write_text(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff'
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff\n'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        testapk = os.path.join('repo', 'com.politedroid_6.apk')
 | 
			
		||||
| 
						 | 
				
			
			@ -1871,8 +1873,8 @@ class UpdateTest(unittest.TestCase):
 | 
			
		|||
        Path('config/categories.yml').write_text('System: {name: System Apps}')
 | 
			
		||||
        os.mkdir('metadata')
 | 
			
		||||
        os.mkdir('repo')
 | 
			
		||||
        Path('config.yml').write_text(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff'
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff\n'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        testapk = os.path.join('repo', 'com.politedroid_6.apk')
 | 
			
		||||
| 
						 | 
				
			
			@ -1901,8 +1903,8 @@ class UpdateTest(unittest.TestCase):
 | 
			
		|||
        Path('config/categories.yml').write_text('System: {name: S}\nTime: {name: T}\n')
 | 
			
		||||
        os.mkdir('metadata')
 | 
			
		||||
        os.mkdir('repo')
 | 
			
		||||
        Path('config.yml').write_text(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff'
 | 
			
		||||
        fdroidserver.common.write_config_file(
 | 
			
		||||
            'repo_pubkey: ffffffffffffffffffffffffffffffffffffffff\n'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        testapk = os.path.join('repo', 'com.politedroid_6.apk')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue