Merge branch 'polish-for-1.0' into 'master'

Polish for 1.0

Closes #421

See merge request fdroid/fdroidserver!388
This commit is contained in:
Hans-Christoph Steiner 2017-11-30 12:28:28 +00:00
commit 2a758886cd
10 changed files with 93 additions and 33 deletions

View file

@ -74,12 +74,25 @@ y
EOH EOH
mkdir -p $ANDROID_HOME/licenses/ mkdir -p $ANDROID_HOME/licenses/
cat << EOF > $ANDROID_HOME/licenses/android-sdk-license cat << EOF > $ANDROID_HOME/licenses/android-sdk-license
8933bad161af4178b1185d1a37fbf41ea5269c55 8933bad161af4178b1185d1a37fbf41ea5269c55
d56f5187479451eabf01fb78af6dfcb131a6481e d56f5187479451eabf01fb78af6dfcb131a6481e
EOF EOF
echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > $ANDROID_HOME/licenses/android-sdk-preview-license
cat <<EOF > $ANDROID_HOME/licenses/android-sdk-preview-license
84831b9409646a918e30573bab4c9c91346d8abd
EOF
cat <<EOF > $ANDROID_HOME/licenses/android-sdk-preview-license-old
79120722343a6f314e0719f863036c702b0e6b2a
84831b9409646a918e30573bab4c9c91346d8abd
EOF
echo y | $ANDROID_HOME/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.1" echo y | $ANDROID_HOME/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.1"
echo y | $ANDROID_HOME/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.1" echo y | $ANDROID_HOME/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.1"
echo y | $ANDROID_HOME/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2" echo y | $ANDROID_HOME/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2"

View file

@ -23,6 +23,7 @@ import shutil
import glob import glob
import subprocess import subprocess
import re import re
import resource
import tarfile import tarfile
import traceback import traceback
import time import time
@ -1120,6 +1121,19 @@ def main():
if not apps: if not apps:
raise FDroidException("No apps to process.") raise FDroidException("No apps to process.")
# make sure enough open files are allowed to process everything
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
if len(apps) > soft:
try:
soft = len(apps) * 2
if soft > hard:
soft = hard
resource.setrlimit(resource.RLIMIT_NOFILE, (soft, hard))
logging.debug(_('Set open file limit to {integer}')
.format(integer=soft))
except (OSError, ValueError) as e:
logging.warning(_('Setting open file limit failed: ') + str(e))
if options.latest: if options.latest:
for app in apps.values(): for app in apps.values():
for build in reversed(app.builds): for build in reversed(app.builds):

View file

@ -40,7 +40,7 @@ import json
import xml.etree.ElementTree as XMLElementTree import xml.etree.ElementTree as XMLElementTree
from binascii import hexlify from binascii import hexlify
from datetime import datetime from datetime import datetime, timedelta
from distutils.version import LooseVersion from distutils.version import LooseVersion
from queue import Queue from queue import Queue
from zipfile import ZipFile from zipfile import ZipFile
@ -444,17 +444,16 @@ def get_local_metadata_files():
return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]') return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]')
def read_pkg_args(args, allow_vercodes=False): def read_pkg_args(appid_versionCode_pairs, allow_vercodes=False):
""" """
:param args: arguments in the form of multiple appid:[vc] strings :param appids: arguments in the form of multiple appid:[vc] strings
:returns: a dictionary with the set of vercodes specified for each package :returns: a dictionary with the set of vercodes specified for each package
""" """
vercodes = {} vercodes = {}
if not args: if not appid_versionCode_pairs:
return vercodes return vercodes
for p in args: for p in appid_versionCode_pairs:
if allow_vercodes and ':' in p: if allow_vercodes and ':' in p:
package, vercode = p.split(':') package, vercode = p.split(':')
else: else:
@ -468,13 +467,17 @@ def read_pkg_args(args, allow_vercodes=False):
return vercodes return vercodes
def read_app_args(args, allapps, allow_vercodes=False): def read_app_args(appid_versionCode_pairs, allapps, allow_vercodes=False):
""" """Build a list of App instances for processing
On top of what read_pkg_args does, this returns the whole app metadata, but
limiting the builds list to the builds matching the vercodes specified. On top of what read_pkg_args does, this returns the whole app
metadata, but limiting the builds list to the builds matching the
appid_versionCode_pairs and vercodes specified. If no appid_versionCode_pairs are specified, then
all App and Build instances are returned.
""" """
vercodes = read_pkg_args(args, allow_vercodes) vercodes = read_pkg_args(appid_versionCode_pairs, allow_vercodes)
if not vercodes: if not vercodes:
return allapps return allapps
@ -1716,6 +1719,23 @@ def natural_key(s):
return [int(sp) if sp.isdigit() else sp for sp in re.split(r'(\d+)', s)] return [int(sp) if sp.isdigit() else sp for sp in re.split(r'(\d+)', s)]
def check_system_clock(dt_obj, path):
"""Check if system clock is updated based on provided date
If an APK has files newer than the system time, suggest updating
the system clock. This is useful for offline systems, used for
signing, which do not have another source of clock sync info. It
has to be more than 24 hours newer because ZIP/APK files do not
store timezone info
"""
checkdt = dt_obj - timedelta(1)
if datetime.today() < checkdt:
logging.warning(_('System clock is older than date in {path}!').format(path=path)
+ '\n' + _('Set clock to that time using:') + '\n'
+ 'sudo date -s "' + str(dt_obj) + '"')
class KnownApks: class KnownApks:
"""permanent store of existing APKs with the date they were added """permanent store of existing APKs with the date they were added
@ -1744,6 +1764,7 @@ class KnownApks:
date = datetime.strptime(t[-1], '%Y-%m-%d') date = datetime.strptime(t[-1], '%Y-%m-%d')
filename = line[0:line.rfind(appid) - 1] filename = line[0:line.rfind(appid) - 1]
self.apks[filename] = (appid, date) self.apks[filename] = (appid, date)
check_system_clock(date, self.path)
self.changed = False self.changed = False
def writeifchanged(self): def writeifchanged(self):

View file

@ -178,6 +178,7 @@ def main():
+ '" does not exist, creating a new keystore there.') + '" does not exist, creating a new keystore there.')
common.write_to_config(test_config, 'keystore', keystore) common.write_to_config(test_config, 'keystore', keystore)
repo_keyalias = None repo_keyalias = None
keydname = None
if options.repo_keyalias: if options.repo_keyalias:
repo_keyalias = options.repo_keyalias repo_keyalias = options.repo_keyalias
common.write_to_config(test_config, 'repo_keyalias', repo_keyalias) common.write_to_config(test_config, 'repo_keyalias', repo_keyalias)
@ -211,7 +212,16 @@ def main():
flags=re.MULTILINE) flags=re.MULTILINE)
with open('opensc-fdroid.cfg', 'w') as f: with open('opensc-fdroid.cfg', 'w') as f:
f.write(opensc_fdroid) f.write(opensc_fdroid)
elif not os.path.exists(keystore): elif os.path.exists(keystore):
to_set = ['keystorepass', 'keypass', 'repo_keyalias', 'keydname']
if repo_keyalias:
to_set.remove('repo_keyalias')
if keydname:
to_set.remove('keydname')
logging.warning('\n' + _('Using existing keystore "{path}"').format(path=keystore)
+ '\n' + _('Now set these in config.py:') + ' '
+ ', '.join(to_set) + '\n')
else:
password = common.genpassword() password = common.genpassword()
c = dict(test_config) c = dict(test_config)
c['keystorepass'] = password c['keystorepass'] = password

View file

@ -155,6 +155,7 @@ def main():
repo_url = repo_base + '/repo' repo_url = repo_base + '/repo'
git_mirror_path = os.path.join(repo_basedir, 'git-mirror') git_mirror_path = os.path.join(repo_basedir, 'git-mirror')
git_mirror_repodir = os.path.join(git_mirror_path, 'fdroid', 'repo') git_mirror_repodir = os.path.join(git_mirror_path, 'fdroid', 'repo')
git_mirror_metadatadir = os.path.join(git_mirror_path, 'fdroid', 'metadata')
if not os.path.isdir(git_mirror_repodir): if not os.path.isdir(git_mirror_repodir):
logging.debug(_('cloning {url}').format(url=clone_url)) logging.debug(_('cloning {url}').format(url=clone_url))
try: try:
@ -186,10 +187,10 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
mirror_git_repo.git.add(all=True) mirror_git_repo.git.add(all=True)
mirror_git_repo.index.commit("update README") mirror_git_repo.index.commit("update README")
icon_path = os.path.join(repo_basedir, 'icon.png') icon_path = os.path.join(git_mirror_path, 'icon.png')
try: try:
import qrcode import qrcode
img = qrcode.make('Some data here') img = qrcode.make(repo_url)
with open(icon_path, 'wb') as fp: with open(icon_path, 'wb') as fp:
fp.write(img) fp.write(img)
except Exception: except Exception:
@ -197,9 +198,13 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
shutil.copy(exampleicon, icon_path) shutil.copy(exampleicon, icon_path)
mirror_git_repo.git.add(all=True) mirror_git_repo.git.add(all=True)
mirror_git_repo.index.commit("update repo/website icon") mirror_git_repo.index.commit("update repo/website icon")
shutil.copy(icon_path, repo_basedir)
os.chdir(repo_basedir) os.chdir(repo_basedir)
common.local_rsync(options, git_mirror_repodir + '/', 'repo/') if os.path.isdir(git_mirror_repodir):
common.local_rsync(options, git_mirror_repodir + '/', 'repo/')
if os.path.isdir(git_mirror_metadatadir):
common.local_rsync(options, git_mirror_metadatadir + '/', 'metadata/')
ssh_private_key_file = _ssh_key_from_debug_keystore() ssh_private_key_file = _ssh_key_from_debug_keystore()
# this is needed for GitPython to find the SSH key # this is needed for GitPython to find the SSH key
@ -254,7 +259,11 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
pass pass
subprocess.check_call(['fdroid', 'update', '--rename-apks', '--verbose'], cwd=repo_basedir) subprocess.check_call(['fdroid', 'update', '--rename-apks', '--create-metadata', '--verbose'],
cwd=repo_basedir)
common.local_rsync(options, repo_basedir + '/metadata/', git_mirror_metadatadir + '/')
mirror_git_repo.git.add(all=True)
mirror_git_repo.index.commit("update app metadata")
try: try:
subprocess.check_call(['fdroid', 'server', 'update', '--verbose'], cwd=repo_basedir) subprocess.check_call(['fdroid', 'server', 'update', '--verbose'], cwd=repo_basedir)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:

View file

@ -513,7 +513,7 @@ def upload_to_virustotal(repo_section, vt_apikey):
with open(outputfilename, 'w') as fp: with open(outputfilename, 'w') as fp:
json.dump(response, fp, indent=2, sort_keys=True) json.dump(response, fp, indent=2, sort_keys=True)
if response.get('positives') > 0: if response.get('positives', 0) > 0:
logging.warning(repofilename + ' has been flagged by virustotal ' logging.warning(repofilename + ' has been flagged by virustotal '
+ str(response['positives']) + ' times:' + str(response['positives']) + ' times:'
+ '\n\t' + response['permalink']) + '\n\t' + response['permalink'])

View file

@ -29,7 +29,7 @@ import zipfile
import hashlib import hashlib
import pickle import pickle
import time import time
from datetime import datetime, timedelta from datetime import datetime
from argparse import ArgumentParser from argparse import ArgumentParser
import collections import collections
@ -1297,22 +1297,11 @@ def process_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk=Fal
apkzip = zipfile.ZipFile(apkfile, 'r') apkzip = zipfile.ZipFile(apkfile, 'r')
# if an APK has files newer than the system time, suggest updating
# the system clock. This is useful for offline systems, used for
# signing, which do not have another source of clock sync info. It
# has to be more than 24 hours newer because ZIP/APK files do not
# store timezone info
manifest = apkzip.getinfo('AndroidManifest.xml') manifest = apkzip.getinfo('AndroidManifest.xml')
if manifest.date_time[1] == 0: # month can't be zero if manifest.date_time[1] == 0: # month can't be zero
logging.debug(_('AndroidManifest.xml has no date')) logging.debug(_('AndroidManifest.xml has no date'))
else: else:
dt_obj = datetime(*manifest.date_time) common.check_system_clock(datetime(*manifest.date_time), apkfilename)
checkdt = dt_obj - timedelta(1)
if datetime.today() < checkdt:
logging.warning('System clock is older than manifest in: '
+ apkfilename
+ '\nSet clock to that time using:\n'
+ 'sudo date -s "' + str(dt_obj) + '"')
# extract icons from APK zip file # extract icons from APK zip file
iconfilename = "%s.%s.png" % (apk['packageName'], apk['versionCode']) iconfilename = "%s.%s.png" % (apk['packageName'], apk['versionCode'])

View file

@ -29,6 +29,8 @@ import textwrap
from .common import FDroidException from .common import FDroidException
from logging import getLogger from logging import getLogger
from fdroidserver import _
logger = getLogger('fdroidserver-vmtools') logger = getLogger('fdroidserver-vmtools')
@ -383,7 +385,9 @@ class LibvirtBuildVm(FDroidBuildVm):
vol = storagePool.storageVolLookupByName(self.srvname + '.img') vol = storagePool.storageVolLookupByName(self.srvname + '.img')
imagepath = vol.path() imagepath = vol.path()
# TODO use a libvirt storage pool to ensure the img file is readable # TODO use a libvirt storage pool to ensure the img file is readable
_check_call(['sudo', '/bin/chmod', '-R', 'a+rX', '/var/lib/libvirt/images']) if not os.access(imagepath, os.R_OK):
logger.warning(_('Cannot read "{path}"!').format(path=imagepath))
_check_call(['sudo', '/bin/chmod', '-R', 'a+rX', '/var/lib/libvirt/images'])
shutil.copy2(imagepath, 'box.img') shutil.copy2(imagepath, 'box.img')
_check_call(['qemu-img', 'rebase', '-p', '-b', '', 'box.img']) _check_call(['qemu-img', 'rebase', '-p', '-b', '', 'box.img'])
img_info_raw = _check_output(['qemu-img', 'info', '--output=json', 'box.img']) img_info_raw = _check_output(['qemu-img', 'info', '--output=json', 'box.img'])

View file

@ -31,7 +31,6 @@ else
echo "No virtualization is used." echo "No virtualization is used."
fi fi
sudo /bin/chmod -R a+rX /var/lib/libvirt/images sudo /bin/chmod -R a+rX /var/lib/libvirt/images
ulimit -n 2048
echo 'maximum allowed number of open file descriptors: ' `ulimit -n` echo 'maximum allowed number of open file descriptors: ' `ulimit -n`
ls -ld /var/lib/libvirt/images ls -ld /var/lib/libvirt/images
ls -l /var/lib/libvirt/images || echo no access ls -l /var/lib/libvirt/images || echo no access

View file

@ -89,6 +89,7 @@ setup(name='fdroidserver',
'pyasn1-modules', 'pyasn1-modules',
'python-vagrant', 'python-vagrant',
'PyYAML', 'PyYAML',
'qrcode',
'ruamel.yaml >= 0.13', 'ruamel.yaml >= 0.13',
'requests >= 2.5.2, != 2.11.0, != 2.12.2, != 2.18.0', 'requests >= 2.5.2, != 2.11.0, != 2.12.2, != 2.18.0',
'docker-py >= 1.9, < 2.0', 'docker-py >= 1.9, < 2.0',