mirror of
https://github.com/f-droid/fdroidserver.git
synced 2025-10-05 08:51:06 +03:00
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:
commit
2a758886cd
10 changed files with 93 additions and 33 deletions
|
@ -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"
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
if os.path.isdir(git_mirror_repodir):
|
||||||
common.local_rsync(options, git_mirror_repodir + '/', 'repo/')
|
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:
|
||||||
|
|
|
@ -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'])
|
||||||
|
|
|
@ -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'])
|
||||||
|
|
|
@ -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,6 +385,8 @@ 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
|
||||||
|
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'])
|
_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'])
|
||||||
|
|
|
@ -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
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -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',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue