Merge branch 'fdroid-build-in-git-repo' into 'master'

run `fdroid build` straight out of an app's git repo

This creates a new metadata file type that is meant to be included in the git repo of the app to be built.  It uses the same formats as `metadata/`, e.g. `.txt`, JSON, XML, YAML.  The filename is instead `.fdroid.(json|txt|xml|yml)`.  This metadata then lets the user run `fdroid build` directly in the git repo of the app, and it will run the build as any other fdroid build.

@mvdan @CiaranG @krt @pserwylo @NicoAlt @parmegv feedback, flames, comments wanted

Given the very raw state of testing Android apps with gitlab-ci, I think this is a great opportunity for fdroidserver to become the standard method for testing Android apps with gitlab-ci, starting with this merge request to provide fdroid metadata embedded in the project.  What still needs to added is something like `fdroid builddepends debian` and `fdroid builddepends android` which reads the metadata and dumps out a list to be fed to `apt-get install` and `android update sdk --no-ui --filter` respectively, so that a *.gitlab-ci.yml* can look like:

```
apt-get -y install fdroidserver
apt-get -y install `fdroid builddepends debian`
echo y | android update sdk --no-ui --all --filter `fdroid builddepends android`
fdroid build
```

Then that would become a template *.gitlab-ci.yml* that should work on most Android apps.

This was marked Work-In-Progress because it depends on !57

See merge request !62
This commit is contained in:
Hans-Christoph Steiner 2016-03-23 20:12:22 +00:00
commit 9e96a288c2
16 changed files with 231 additions and 98 deletions

View file

@ -314,7 +314,7 @@ To build a single version of a single application, you could run the
following: following:
@example @example
./fdroid build org.fdroid.fdroid:16 fdroid build org.fdroid.fdroid:16
@end example @end example
This attempts to build version code 16 (which is version 0.25) of the F-Droid This attempts to build version code 16 (which is version 0.25) of the F-Droid
@ -336,7 +336,7 @@ tarball containing exactly the source that was used to generate the binary.
If you were intending to publish these files, you could then run: If you were intending to publish these files, you could then run:
@example @example
./fdroid publish fdroid publish
@end example @end example
The source tarball would move to the @code{repo} directory (which is the The source tarball would move to the @code{repo} directory (which is the
@ -366,6 +366,26 @@ all such prebuilts are built either via the metadata or by a reputable third
party. party.
@section Running "fdroid build" in your app's source
Another option for using @code{fdroid build} is to use a metadata file
that is included in the app's source itself, rather than in a
@code{metadata/} folder with lots of other apps. This metadata file
should be in the root of your source repo, and be called
@code{.fdroid.json}, @code{.fdroid.xml}, @code{.fdroid.yaml}, or
@code{.fdroid.txt}, depending on your preferred data format: JSON,
XML, YAML, or F-Droid's @code{.txt} format.
Once you have that setup, you can build the most recent version of
the app using the whole FDroid stack by running:
@example
fdroid build
@end example
If you want to build every single version, then specify @code{--all}.
@section Direct Installation @section Direct Installation
You can also build and install directly to a connected device or emulator You can also build and install directly to a connected device or emulator
@ -381,19 +401,32 @@ the signed output directory were modified, you won't be notified.
@node Importing Applications @node Importing Applications
@chapter Importing Applications @chapter Importing Applications
To help with starting work on including a new application, @code{fdroid import} To help with starting work on including a new application, use
will take a URL and optionally some other parameters, and attempt to construct @code{fdroid import} to set up a new template project. It has two
as much information as possible by analysing the source code. Basic usage is: modes of operation, starting with a cloned git repo:
@example @example
./fdroid import --url=http://address.of.project git clone https://gitlab.com/fdroid/fdroidclient
cd fdroidclient
fdroid import
@end example @end example
For this to work, the URL must point to a project format that the script Or starting with a URL to a project page:
@example
fdroid import --url=http://address.of.project
@end example
When a URL is specified using the @code{--url=} flag, @code{fdroid
import} will use that URL to find out information about the project,
and if it finds a git repo, it will also clone that. For this to
work, the URL must point to a project format that the script
understands. Currently this is limited to one of the following: understands. Currently this is limited to one of the following:
@enumerate @enumerate
@item @item
GitLab - @code{https://gitlab.com/PROJECTNAME/REPONAME}
@item
Gitorious - @code{https://gitorious.org/PROJECTNAME/REPONAME} Gitorious - @code{https://gitorious.org/PROJECTNAME/REPONAME}
@item @item
Github - @code{https://github.com/USER/PROJECT} Github - @code{https://github.com/USER/PROJECT}

View file

@ -472,13 +472,7 @@ def build_local(app, build, vcs, build_dir, output_dir, srclib_dir, extlib_dir,
logging.critical("Android NDK '%s' is not a directory!" % ndk_path) logging.critical("Android NDK '%s' is not a directory!" % ndk_path)
sys.exit(3) sys.exit(3)
# Set up environment vars that depend on each build common.set_FDroidPopen_env(build)
for n in ['ANDROID_NDK', 'NDK', 'ANDROID_NDK_HOME']:
common.env[n] = ndk_path
common.reset_env_path()
# Set up the current NDK to the PATH
common.add_to_env_path(ndk_path)
# Prepare the source code... # Prepare the source code...
root_dir, srclibpaths = common.prepare_source(vcs, app, build, root_dir, srclibpaths = common.prepare_source(vcs, app, build,
@ -1008,17 +1002,25 @@ def main():
options, parser = parse_commandline() options, parser = parse_commandline()
metadata_files = glob.glob('.fdroid.*[a-z]') # ignore files ending in ~ # The defaults for .fdroid.* metadata that is included in a git repo are
if os.path.isdir('metadata'): # different than for the standard metadata/ layout because expectations
pass # are different. In this case, the most common user will be the app
elif len(metadata_files) == 0: # developer working on the latest update of the app on their own machine.
raise FDroidException("No app metadata found, nothing to process!") local_metadata_files = common.get_local_local_metadata_files()
elif len(metadata_files) > 1: if len(local_metadata_files) == 1: # there is local metadata in an app's source
config = dict(common.default_config)
# `fdroid build` should build only the latest version by default since
# most of the time the user will be building the most recent update
if not options.all:
options.latest = True
elif len(local_metadata_files) > 1:
raise FDroidException("Only one local metadata file allowed! Found: " raise FDroidException("Only one local metadata file allowed! Found: "
+ " ".join(metadata_files)) + " ".join(local_metadata_files))
else:
if not options.appid and not options.all: if not os.path.isdir('metadata') and len(local_metadata_files) == 0:
parser.error("option %s: If you really want to build all the apps, use --all" % "all") raise FDroidException("No app metadata found, nothing to process!")
if not options.appid and not options.all:
parser.error("option %s: If you really want to build all the apps, use --all" % "all")
config = common.read_config(options) config = common.read_config(options)

View file

@ -492,8 +492,7 @@ def checkupdates_app(app, first=True):
if commitmsg: if commitmsg:
metadatapath = os.path.join('metadata', app.id + '.txt') metadatapath = os.path.join('metadata', app.id + '.txt')
with open(metadatapath, 'w') as f: metadata.write_metadata(metadatapath, app)
metadata.write_metadata('txt', f, app)
if options.commit: if options.commit:
logging.info("Commiting update for " + metadatapath) logging.info("Commiting update for " + metadatapath)
gitcmd = ["git", "commit", "-m", commitmsg] gitcmd = ["git", "commit", "-m", commitmsg]

View file

@ -63,7 +63,7 @@ default_config = {
'ant': "ant", 'ant': "ant",
'mvn3': "mvn", 'mvn3': "mvn",
'gradle': 'gradle', 'gradle': 'gradle',
'accepted_formats': ['txt', 'yaml'], 'accepted_formats': ['txt', 'yml'],
'sync_from_local_copy_dir': False, 'sync_from_local_copy_dir': False,
'per_app_repos': False, 'per_app_repos': False,
'make_current_version_link': True, 'make_current_version_link': True,
@ -194,25 +194,29 @@ def regsub_file(pattern, repl, path):
def read_config(opts, config_file='config.py'): def read_config(opts, config_file='config.py'):
"""Read the repository config """Read the repository config
The config is read from config_file, which is in the current directory when The config is read from config_file, which is in the current
any of the repo management commands are used. directory when any of the repo management commands are used. If
there is a local metadata file in the git repo, then config.py is
not required, just use defaults.
""" """
global config, options, env, orig_path global config, options
if config is not None: if config is not None:
return config return config
if not os.path.isfile(config_file):
logging.critical("Missing config file - is this a repo directory?")
sys.exit(2)
options = opts options = opts
config = {} config = {}
logging.debug("Reading %s" % config_file) if os.path.isfile(config_file):
with io.open(config_file, "rb") as f: logging.debug("Reading %s" % config_file)
code = compile(f.read(), config_file, 'exec') with io.open(config_file, "rb") as f:
exec(code, None, config) code = compile(f.read(), config_file, 'exec')
exec(code, None, config)
elif len(get_local_metadata_files()) == 0:
logging.critical("Missing config file - is this a repo directory?")
sys.exit(2)
# smartcardoptions must be a list since its command line args for Popen # smartcardoptions must be a list since its command line args for Popen
if 'smartcardoptions' in config: if 'smartcardoptions' in config:
@ -231,16 +235,6 @@ def read_config(opts, config_file='config.py'):
fill_config_defaults(config) fill_config_defaults(config)
# There is no standard, so just set up the most common environment
# variables
env = os.environ
orig_path = env['PATH']
for n in ['ANDROID_HOME', 'ANDROID_SDK']:
env[n] = config['sdk_path']
for k, v in config['java_paths'].items():
env['JAVA%s_HOME' % k] = v
for k in ["keystorepass", "keypass"]: for k in ["keystorepass", "keypass"]:
if k in config: if k in config:
write_password_file(k) write_password_file(k)
@ -268,6 +262,21 @@ def read_config(opts, config_file='config.py'):
return config return config
def get_ndk_path(version):
if config is None or 'ndk_paths' not in config:
ndk_path = os.getenv('ANDROID_NDK_HOME')
if ndk_path is None:
logging.error('No NDK found! Either set ANDROID_NDK_HOME or add ndk_path to your config.py')
else:
return ndk_path
if version is None:
version = 'r10e' # falls back to latest
paths = config['ndk_paths']
if version not in paths:
return ''
return paths[version] or ''
def find_sdk_tools_cmd(cmd): def find_sdk_tools_cmd(cmd):
'''find a working path to a tool from the Android SDK''' '''find a working path to a tool from the Android SDK'''
@ -352,6 +361,16 @@ def write_password_file(pwtype, password=None):
config[pwtype + 'file'] = filename config[pwtype + 'file'] = filename
def get_local_metadata_files():
'''get any metadata files local to an app's source repo
This tries to ignore anything that does not count as app metdata,
including emacs cruft ending in ~ and the .fdroid.key*pass.txt files.
'''
return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]')
# Given the arguments in the form of multiple appid:[vc] strings, this returns # Given the arguments in the form of multiple appid:[vc] strings, this returns
# a dictionary with the set of vercodes specified for each package. # a dictionary with the set of vercodes specified for each package.
def read_pkg_args(args, allow_vercodes=False): def read_pkg_args(args, allow_vercodes=False):
@ -1639,6 +1658,8 @@ def FDroidPopenBytes(commands, cwd=None, output=True, stderr_to_stdout=True):
""" """
global env global env
if env is None:
set_FDroidPopen_env()
if cwd: if cwd:
cwd = os.path.normpath(cwd) cwd = os.path.normpath(cwd)
@ -1780,25 +1801,40 @@ def remove_signing_keys(build_dir):
logging.info("Cleaned %s of keysigning configs at %s" % (propfile, path)) logging.info("Cleaned %s of keysigning configs at %s" % (propfile, path))
def reset_env_path(): def set_FDroidPopen_env(build=None):
'''
set up the environment variables for the build environment
There is only a weak standard, the variables used by gradle, so also set
up the most commonly used environment variables for SDK and NDK
'''
global env, orig_path global env, orig_path
env['PATH'] = orig_path
if env is None:
env = os.environ
orig_path = env['PATH']
for n in ['ANDROID_HOME', 'ANDROID_SDK']:
env[n] = config['sdk_path']
for k, v in config['java_paths'].items():
env['JAVA%s_HOME' % k] = v
def add_to_env_path(path): # Set up environment vars that depend on each build, only set the
global env # NDK env vars if the NDK is not already in the PATH
paths = env['PATH'].split(os.pathsep) if build is not None:
if path in paths: path = build.ndk_path()
return paths = orig_path.split(os.pathsep)
paths.append(path) if path in paths:
env['PATH'] = os.pathsep.join(paths) return
paths.append(path)
env['PATH'] = os.pathsep.join(paths)
for n in ['ANDROID_NDK', 'NDK', 'ANDROID_NDK_HOME']:
env[n] = build.ndk_path()
def replace_config_vars(cmd, build): def replace_config_vars(cmd, build):
global env
cmd = cmd.replace('$$SDK$$', config['sdk_path']) cmd = cmd.replace('$$SDK$$', config['sdk_path'])
# env['ANDROID_NDK'] is set in build_local right before prepare_source cmd = cmd.replace('$$NDK$$', get_ndk_path(build['ndk']))
cmd = cmd.replace('$$NDK$$', env['ANDROID_NDK'])
cmd = cmd.replace('$$MVN3$$', config['mvn3']) cmd = cmd.replace('$$MVN3$$', config['mvn3'])
if build is not None: if build is not None:
cmd = cmd.replace('$$COMMIT$$', build.commit) cmd = cmd.replace('$$COMMIT$$', build.commit)

View file

@ -17,6 +17,7 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import binascii
import sys import sys
import os import os
import shutil import shutil
@ -180,12 +181,38 @@ def main():
root_dir = None root_dir = None
build_dir = None build_dir = None
if options.url: local_metadata_files = common.get_local_metadata_files()
root_dir, build_dir = get_metadata_from_url(app, options.url) if local_metadata_files != []:
elif os.path.isdir('.git'): logging.error("This repo already has local metadata: %s" % local_metadata_files[0])
if options.url: sys.exit(1)
app.WebSite = options.url
if options.url is None and os.path.isdir('.git'):
app.AutoName = os.path.basename(os.getcwd())
app.RepoType = 'git'
build = {}
root_dir = get_subdir(os.getcwd()) root_dir = get_subdir(os.getcwd())
if os.path.exists('build.gradle'):
build.gradle = ['yes']
import git
repo = git.repo.Repo(root_dir) # git repo
for remote in git.Remote.iter_items(repo):
if remote.name == 'origin':
url = repo.remotes.origin.url
if url.startswith('https://git'): # github, gitlab
app.SourceCode = url.rstrip('.git')
app.Repo = url
break
# repo.head.commit.binsha is a bytearray stored in a str
build.commit = binascii.hexlify(bytearray(repo.head.commit.binsha))
write_local_file = True
elif options.url:
root_dir, build_dir = get_metadata_from_url(app, options.url)
build = metadata.Build()
build.commit = '?'
build.disable = 'Generated by import.py - check/set version fields and commit id'
write_local_file = False
else: else:
logging.error("Specify project url.") logging.error("Specify project url.")
sys.exit(1) sys.exit(1)
@ -222,30 +249,31 @@ def main():
sys.exit(1) sys.exit(1)
# Create a build line... # Create a build line...
build = metadata.Build()
build.version = version or '?' build.version = version or '?'
build.vercode = vercode or '?' build.vercode = vercode or '?'
build.commit = '?'
build.disable = 'Generated by import.py - check/set version fields and commit id'
if options.subdir: if options.subdir:
build.subdir = options.subdir build.subdir = options.subdir
if os.path.exists(os.path.join(root_dir, 'jni')): if os.path.exists(os.path.join(root_dir, 'jni')):
build.buildjni = ['yes'] build.buildjni = ['yes']
metadata.post_metadata_parse(app)
app.builds.append(build) app.builds.append(build)
# Keep the repo directory to save bandwidth... if write_local_file:
if not os.path.exists('build'): metadata.write_metadata('.fdroid.yml', app)
os.mkdir('build') else:
if build_dir is not None: # Keep the repo directory to save bandwidth...
shutil.move(build_dir, os.path.join('build', package)) if not os.path.exists('build'):
with open('build/.fdroidvcs-' + package, 'w') as f: os.mkdir('build')
f.write(app.RepoType + ' ' + app.Repo) if build_dir is not None:
shutil.move(build_dir, os.path.join('build', package))
with open('build/.fdroidvcs-' + package, 'w') as f:
f.write(app.RepoType + ' ' + app.Repo)
metadatapath = os.path.join('metadata', package + '.txt') metadatapath = os.path.join('metadata', package + '.txt')
with open(metadatapath, 'w') as f: metadata.write_metadata(metadatapath, app)
metadata.write_metadata('txt', f, app) logging.info("Wrote " + metadatapath)
logging.info("Wrote " + metadatapath)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -22,6 +22,7 @@ import os
import re import re
import glob import glob
import cgi import cgi
import logging
import textwrap import textwrap
import io import io
@ -778,7 +779,10 @@ def read_metadata(xref=True):
for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.txt')) for metadatapath in sorted(glob.glob(os.path.join('metadata', '*.txt'))
+ glob.glob(os.path.join('metadata', '*.json')) + glob.glob(os.path.join('metadata', '*.json'))
+ glob.glob(os.path.join('metadata', '*.xml')) + glob.glob(os.path.join('metadata', '*.xml'))
+ glob.glob(os.path.join('metadata', '*.yaml'))): + glob.glob(os.path.join('metadata', '*.yml'))
+ glob.glob('.fdroid.json')
+ glob.glob('.fdroid.xml')
+ glob.glob('.fdroid.yml')):
app = parse_metadata(metadatapath) app = parse_metadata(metadatapath)
if app.id in apps: if app.id in apps:
raise MetaDataException("Found multiple metadata files for " + app.id) raise MetaDataException("Found multiple metadata files for " + app.id)
@ -824,6 +828,25 @@ def get_default_app_info(metadatapath=None):
else: else:
appid, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath)) appid, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath))
if appid == '.fdroid': # we have local metadata in the app's source
if os.path.exists('AndroidManifest.xml'):
manifestroot = fdroidserver.common.parse_xml('AndroidManifest.xml')
else:
pattern = re.compile(""".*manifest\.srcFile\s+'AndroidManifest\.xml'.*""")
for root, dirs, files in os.walk(os.getcwd()):
if 'build.gradle' in files:
p = os.path.join(root, 'build.gradle')
with open(p) as f:
data = f.read()
m = pattern.search(data)
if m:
logging.debug('Using: ' + os.path.join(root, 'AndroidManifest.xml'))
manifestroot = fdroidserver.common.parse_xml(os.path.join(root, 'AndroidManifest.xml'))
break
if manifestroot is None:
raise MetaDataException("Cannot find a packageName for {0}!".format(metadatapath))
appid = manifestroot.attrib['package']
app = App() app = App()
app.metadatapath = metadatapath app.metadatapath = metadatapath
if appid is not None: if appid is not None:
@ -927,7 +950,7 @@ def parse_metadata(metadatapath):
parse_json_metadata(mf, app) parse_json_metadata(mf, app)
elif ext == 'xml': elif ext == 'xml':
parse_xml_metadata(mf, app) parse_xml_metadata(mf, app)
elif ext == 'yaml': elif ext == 'yml':
parse_yaml_metadata(mf, app) parse_yaml_metadata(mf, app)
else: else:
raise MetaDataException('Unknown metadata format: %s' % metadatapath) raise MetaDataException('Unknown metadata format: %s' % metadatapath)
@ -1247,7 +1270,7 @@ def write_plaintext_metadata(mf, app, w_comment, w_field, w_build):
# #
# 'mf' - Writer interface (file, StringIO, ...) # 'mf' - Writer interface (file, StringIO, ...)
# 'app' - The app data # 'app' - The app data
def write_txt_metadata(mf, app): def write_txt(mf, app):
def w_comment(line): def w_comment(line):
mf.write("# %s\n" % line) mf.write("# %s\n" % line)
@ -1290,7 +1313,7 @@ def write_txt_metadata(mf, app):
write_plaintext_metadata(mf, app, w_comment, w_field, w_build) write_plaintext_metadata(mf, app, w_comment, w_field, w_build)
def write_yaml_metadata(mf, app): def write_yaml(mf, app):
def w_comment(line): def w_comment(line):
mf.write("# %s\n" % line) mf.write("# %s\n" % line)
@ -1354,9 +1377,16 @@ def write_yaml_metadata(mf, app):
write_plaintext_metadata(mf, app, w_comment, w_field, w_build) write_plaintext_metadata(mf, app, w_comment, w_field, w_build)
def write_metadata(fmt, mf, app): def write_metadata(metadatapath, app):
if fmt == 'txt': _, ext = fdroidserver.common.get_extension(metadatapath)
return write_txt_metadata(mf, app) accepted = fdroidserver.common.config['accepted_formats']
if fmt == 'yaml': if ext not in accepted:
return write_yaml_metadata(mf, app) raise MetaDataException('Cannot write "%s", not an accepted format, use: %s' % (
raise MetaDataException("Unknown metadata format given") metadatapath, ', '.join(accepted)))
with open(metadatapath, 'w') as mf:
if ext == 'txt':
return write_txt(mf, app)
elif ext == 'yml':
return write_yaml(mf, app)
raise MetaDataException('Unknown metadata format: %s' % metadatapath)

View file

@ -64,7 +64,7 @@ def main():
if options.list and options.to is not None: if options.list and options.to is not None:
parser.error("Cannot use --list and --to at the same time") parser.error("Cannot use --list and --to at the same time")
supported = ['txt', 'yaml'] supported = ['txt', 'yml']
if options.to is not None and options.to not in supported: if options.to is not None and options.to not in supported:
parser.error("Must give a valid format to --to") parser.error("Must give a valid format to --to")
@ -84,8 +84,7 @@ def main():
print(app.metadatapath) print(app.metadatapath)
continue continue
with open(base + '.' + to_ext, 'w') as f: metadata.write_metadata(base + '.' + to_ext, app)
metadata.write_metadata(to_ext, f, app)
if ext != to_ext: if ext != to_ext:
os.remove(app.metadatapath) os.remove(app.metadatapath)

View file

@ -27,6 +27,7 @@ setup(name='fdroidserver',
'examples/fdroid-icon.png']), 'examples/fdroid-icon.png']),
], ],
install_requires=[ install_requires=[
'GitPython',
'mwclient', 'mwclient',
'paramiko', 'paramiko',
'Pillow', 'Pillow',

View file

@ -64,7 +64,7 @@ class CommonTest(unittest.TestCase):
def testIsApkDebuggable(self): def testIsApkDebuggable(self):
config = dict() config = dict()
config['sdk_path'] = os.getenv('ANDROID_HOME') fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
self._set_build_tools() self._set_build_tools()
config['aapt'] = fdroidserver.common.find_sdk_tools_cmd('aapt') config['aapt'] = fdroidserver.common.find_sdk_tools_cmd('aapt')

View file

@ -25,8 +25,9 @@ class ImportTest(unittest.TestCase):
def test_import_gitlab(self): def test_import_gitlab(self):
# FDroidPopen needs some config to work # FDroidPopen needs some config to work
fdroidserver.common.config = dict() config = dict()
fdroidserver.common.config['sdk_path'] = '/fake/path/to/android-sdk' fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config
url = 'https://gitlab.com/fdroid/fdroidclient' url = 'https://gitlab.com/fdroid/fdroidclient'
app = fdroidserver.metadata.get_default_app_info() app = fdroidserver.metadata.get_default_app_info()

View file

@ -23,7 +23,7 @@ class InstallTest(unittest.TestCase):
def test_devices(self): def test_devices(self):
config = dict() config = dict()
config['sdk_path'] = os.getenv('ANDROID_HOME') fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
config['adb'] = fdroidserver.common.find_sdk_tools_cmd('adb') config['adb'] = fdroidserver.common.find_sdk_tools_cmd('adb')
self.assertTrue(os.path.exists(config['adb'])) self.assertTrue(os.path.exists(config['adb']))

View file

@ -33,7 +33,7 @@ class MetadataTest(unittest.TestCase):
config = dict() config = dict()
config['sdk_path'] = '/opt/android-sdk' config['sdk_path'] = '/opt/android-sdk'
config['ndk_paths'] = dict() config['ndk_paths'] = dict()
config['accepted_formats'] = ['json', 'txt', 'xml', 'yaml'] config['accepted_formats'] = ['json', 'txt', 'xml', 'yml']
fdroidserver.common.config = config fdroidserver.common.config = config
apps = fdroidserver.metadata.read_metadata(xref=True) apps = fdroidserver.metadata.read_metadata(xref=True)

View file

@ -4618,7 +4618,7 @@ sasS'FlattrID'
p1324 p1324
NsS'metadatapath' NsS'metadatapath'
p1325 p1325
S'metadata/org.videolan.vlc.yaml' S'metadata/org.videolan.vlc.yml'
p1326 p1326
sS'Disabled' sS'Disabled'
p1327 p1327

View file

@ -163,7 +163,7 @@ cp $WORKSPACE/tests/metadata/org.smssecure.smssecure.txt $REPOROOT/metadata/
$fdroid readmeta $fdroid readmeta
# now make a fake duplicate # now make a fake duplicate
touch $REPOROOT/metadata/org.smssecure.smssecure.yaml touch $REPOROOT/metadata/org.smssecure.smssecure.yml
set +e set +e
$fdroid readmeta $fdroid readmeta

View file

@ -29,6 +29,10 @@ class UpdateTest(unittest.TestCase):
if not os.path.exists(getsig_dir + "/getsig.class"): if not os.path.exists(getsig_dir + "/getsig.class"):
logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir) logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
sys.exit(1) sys.exit(1)
# FDroidPopen needs some config to work
config = dict()
fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config
p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'), p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
'getsig', os.path.join(os.getcwd(), apkfile)]) 'getsig', os.path.join(os.getcwd(), apkfile)])
sig = None sig = None