1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-08-15 10:50:09 +02:00

Replace sys.exit() in non-main functions by exceptions

Also move all exceptions into one module
This commit is contained in:
Torsten Grote 2017-05-22 16:33:52 -03:00
parent a8420817cb
commit 1fcd8e63a3
No known key found for this signature in database
GPG Key ID: 3E5F77D92CF891FF
17 changed files with 119 additions and 141 deletions

View File

@ -35,12 +35,12 @@ import json
import logging
import requests
import shutil
import sys
import tempfile
import xml.dom.minidom
import zipfile
from argparse import ArgumentParser
from .exception import FDroidException
from . import common
from . import server
@ -166,8 +166,8 @@ def main():
logging.getLogger("urllib3").setLevel(logging.WARNING)
if not os.path.exists(options.git_repo):
logging.error('"' + options.git_repo + '/" does not exist! Create it, or use --git-repo')
sys.exit(1)
raise FDroidException(
'"%s" does not exist! Create it, or use --git-repo' % options.git_repo)
session = requests.Session()

View File

@ -37,7 +37,8 @@ from . import common
from . import net
from . import metadata
from . import scanner
from .common import FDroidException, BuildException, VCSException, FDroidPopen, SdkToolsPopen
from .common import FDroidPopen, SdkToolsPopen
from .exception import FDroidException, BuildException, VCSException
try:
import paramiko
@ -582,10 +583,10 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext
if k.endswith("_orig"):
continue
logging.critical(" %s: %s" % (k, v))
sys.exit(3)
raise FDroidException()
elif not os.path.isdir(ndk_path):
logging.critical("Android NDK '%s' is not a directory!" % ndk_path)
sys.exit(3)
raise FDroidException()
common.set_FDroidPopen_env(build)
@ -1256,7 +1257,8 @@ def main():
try:
net.download_file(url, local_filename=of)
except requests.exceptions.HTTPError as e:
raise FDroidException('downloading Binaries from %s failed' % url) from e
raise FDroidException(
'Downloading Binaries from %s failed. %s' % (url, e))
# Now we check weather the build can be verified to
# match the supplied binary or not. Should the

View File

@ -17,7 +17,6 @@
# 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/>.
import sys
import os
import re
import urllib.request
@ -33,8 +32,7 @@ import copy
from . import common
from . import metadata
from .common import VCSException, FDroidException
from .metadata import MetaDataException
from .exception import VCSException, FDroidException, MetaDataException
# Check for a new version by looking at a document retrieved via HTTP.
@ -498,8 +496,7 @@ def checkupdates_app(app, first=True):
gitcmd.extend(['--author', config['auto_author']])
gitcmd.extend(["--", metadatapath])
if subprocess.call(gitcmd) != 0:
logging.error("Git commit failed")
sys.exit(1)
raise FDroidException("Git commit failed")
config = None

View File

@ -49,6 +49,7 @@ from pyasn1.error import PyAsn1Error
from distutils.util import strtobool
import fdroidserver.metadata
from fdroidserver.exception import FDroidException, VCSException, BuildException
from .asynchronousfilereader import AsynchronousFileReader
@ -234,8 +235,7 @@ def read_config(opts, config_file='config.py'):
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)
raise FDroidException("Missing config file - is this a repo directory?")
for k in ('mirrors', 'install_list', 'uninstall_list', 'serverwebroot', 'servergitroot'):
if k in config:
@ -374,13 +374,12 @@ def test_sdk_exists(thisconfig):
def ensure_build_tools_exists(thisconfig):
if not test_sdk_exists(thisconfig):
sys.exit(3)
raise FDroidException("Android SDK not found.")
build_tools = os.path.join(thisconfig['sdk_path'], 'build-tools')
versioned_build_tools = os.path.join(build_tools, thisconfig['build_tools'])
if not os.path.isdir(versioned_build_tools):
logging.critical('Android Build Tools path "'
+ versioned_build_tools + '" does not exist!')
sys.exit(3)
raise FDroidException(
'Android Build Tools path "' + versioned_build_tools + '" does not exist!')
def get_local_metadata_files():
@ -1243,39 +1242,6 @@ def is_valid_package_name(name):
return re.match("[A-Za-z_][A-Za-z_0-9.]+$", name)
class FDroidException(Exception):
def __init__(self, value, detail=None):
self.value = value
self.detail = detail
def shortened_detail(self):
if len(self.detail) < 16000:
return self.detail
return '[...]\n' + self.detail[-16000:]
def get_wikitext(self):
ret = repr(self.value) + "\n"
if self.detail:
ret += "=detail=\n"
ret += "<pre>\n" + self.shortened_detail() + "</pre>\n"
return ret
def __str__(self):
ret = self.value
if self.detail:
ret += "\n==== detail begin ====\n%s\n==== detail end ====" % self.detail.strip()
return ret
class VCSException(FDroidException):
pass
class BuildException(FDroidException):
pass
# Get the specified source library.
# Returns the path to it. Normally this is the path to be used when referencing
# it, which may be a subdirectory of the actual project. If you want the base
@ -1696,8 +1662,7 @@ def get_apk_debuggable_aapt(apkfile):
p = SdkToolsPopen(['aapt', 'dump', 'xmltree', apkfile, 'AndroidManifest.xml'],
output=False)
if p.returncode != 0:
logging.critical("Failed to get apk manifest information")
sys.exit(1)
raise FDroidException("Failed to get apk manifest information")
for line in p.output.splitlines():
if 'android:debuggable' in line and not line.endswith('0x0'):
return True
@ -1708,8 +1673,7 @@ def get_apk_debuggable_androguard(apkfile):
try:
from androguard.core.bytecodes.apk import APK
except ImportError:
logging.critical("androguard library is not installed and aapt not present")
sys.exit(1)
raise FDroidException("androguard library is not installed and aapt not present")
apkobject = APK(apkfile)
if apkobject.is_valid_APK():
@ -1745,8 +1709,7 @@ def SdkToolsPopen(commands, cwd=None, output=True):
config[cmd] = find_sdk_tools_cmd(commands[0])
abscmd = config[cmd]
if abscmd is None:
logging.critical("Could not find '%s' on your system" % cmd)
sys.exit(1)
raise FDroidException("Could not find '%s' on your system" % cmd)
if cmd == 'aapt':
test_aapt_version(config['aapt'])
return FDroidPopen([abscmd] + commands[1:],

44
fdroidserver/exception.py Normal file
View File

@ -0,0 +1,44 @@
class FDroidException(Exception):
def __init__(self, value=None, detail=None):
self.value = value
self.detail = detail
def shortened_detail(self):
if len(self.detail) < 16000:
return self.detail
return '[...]\n' + self.detail[-16000:]
def get_wikitext(self):
ret = repr(self.value) + "\n"
if self.detail:
ret += "=detail=\n"
ret += "<pre>\n" + self.shortened_detail() + "</pre>\n"
return ret
def __str__(self):
ret = self.value
if self.detail:
ret += "\n==== detail begin ====\n%s\n==== detail end ====" % self.detail.strip()
return ret
class MetaDataException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
class VCSException(FDroidException):
pass
class BuildException(FDroidException):
pass
class VerificationException(FDroidException):
pass

View File

@ -16,7 +16,6 @@
# 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/>.
import sys
import os
import glob
from argparse import ArgumentParser
@ -24,6 +23,7 @@ import logging
from . import common
from .common import FDroidPopen
from .exception import FDroidException
config = None
options = None
@ -46,8 +46,7 @@ def main():
for output_dir in repodirs:
if not os.path.isdir(output_dir):
logging.error("Missing output directory '" + output_dir + "'")
sys.exit(1)
raise FDroidException("Missing output directory '" + output_dir + "'")
# Process any apks that are waiting to be signed...
for f in sorted(glob.glob(os.path.join(output_dir, '*.*'))):
@ -70,8 +69,7 @@ def main():
gpgargs.append(os.path.join(output_dir, filename))
p = FDroidPopen(gpgargs)
if p.returncode != 0:
logging.error("Signing failed.")
sys.exit(1)
raise FDroidException("Signing failed.")
logging.info('Signed ' + filename)

View File

@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import binascii
import sys
import os
import shutil
import urllib.request
@ -28,6 +27,7 @@ import logging
from . import common
from . import metadata
from .exception import FDroidException
# Get the repo type and address from the given web page. The page is scanned
@ -123,8 +123,7 @@ def get_metadata_from_url(app, url):
# Figure out the repo type and adddress...
repotype, repo = getrepofrompage(app.SourceCode)
if not repotype:
logging.error("Unable to determine vcs type. " + repo)
sys.exit(1)
raise FDroidException("Unable to determine vcs type. " + repo)
elif url.startswith('https://') and url.endswith('.git'):
projecttype = 'git'
repo = url
@ -132,10 +131,10 @@ def get_metadata_from_url(app, url):
app.SourceCode = ""
app.WebSite = ""
if not projecttype:
logging.error("Unable to determine the project type.")
logging.error("The URL you supplied was not in one of the supported formats. Please consult")
logging.error("the manual for a list of supported formats, and supply one of those.")
sys.exit(1)
raise FDroidException("Unable to determine the project type. " +
"The URL you supplied was not in one of the supported formats. " +
"Please consult the manual for a list of supported formats, " +
"and supply one of those.")
# Ensure we have a sensible-looking repo address at this point. If not, we
# might have got a page format we weren't expecting. (Note that we
@ -144,8 +143,7 @@ def get_metadata_from_url(app, url):
not repo.startswith('https://') and
not repo.startswith('git://'))) or
' ' in repo):
logging.error("Repo address '{0}' does not seem to be valid".format(repo))
sys.exit(1)
raise FDroidException("Repo address '{0}' does not seem to be valid".format(repo))
# Get a copy of the source so we can extract some info...
logging.info('Getting source from ' + repotype + ' repo at ' + repo)
@ -205,8 +203,7 @@ def main():
local_metadata_files = common.get_local_metadata_files()
if local_metadata_files != []:
logging.error("This repo already has local metadata: %s" % local_metadata_files[0])
sys.exit(1)
raise FDroidException("This repo already has local metadata: %s" % local_metadata_files[0])
if options.url is None and os.path.isdir('.git'):
app.AutoName = os.path.basename(os.getcwd())
@ -236,8 +233,7 @@ def main():
build.disable = 'Generated by import.py - check/set version fields and commit id'
write_local_file = False
else:
logging.error("Specify project url.")
sys.exit(1)
raise FDroidException("Specify project url.")
# Extract some information...
paths = common.manifest_paths(root_dir, [])
@ -245,8 +241,7 @@ def main():
versionName, versionCode, package = common.parse_androidmanifests(paths, app)
if not package:
logging.error("Couldn't find package ID")
sys.exit(1)
raise FDroidException("Couldn't find package ID")
if not versionName:
logging.warn("Couldn't find latest version name")
if not versionCode:
@ -262,13 +257,11 @@ def main():
versionName = bconfig.get('app', 'version')
versionCode = None
else:
logging.error("No android or kivy project could be found. Specify --subdir?")
sys.exit(1)
raise FDroidException("No android or kivy project could be found. Specify --subdir?")
# Make sure it's actually new...
if package in apps:
logging.error("Package " + package + " already exists")
sys.exit(1)
raise FDroidException("Package " + package + " already exists")
# Create a build line...
build.versionName = versionName or '?'

View File

@ -27,7 +27,6 @@ import logging
import os
import re
import shutil
import sys
import tempfile
import urllib.parse
import zipfile
@ -37,7 +36,7 @@ from xml.dom.minidom import Document
from fdroidserver import metadata, signindex, common, net
from fdroidserver.common import FDroidPopen, FDroidPopenBytes
from fdroidserver.metadata import MetaDataException
from fdroidserver.exception import FDroidException, VerificationException, MetaDataException
def make(apps, sortedids, apks, repodir, archive):
@ -77,9 +76,8 @@ def make(apps, sortedids, apks, repodir, archive):
nosigningkey = True
logging.critical("'" + common.config['keystore'] + "' does not exist!")
if nosigningkey:
logging.warning("`fdroid update` requires a signing key, you can create one using:")
logging.warning("\tfdroid update --create-key")
sys.exit(1)
raise FDroidException("`fdroid update` requires a signing key, " +
"you can create one using: fdroid update --create-key")
repodict = collections.OrderedDict()
repodict['timestamp'] = datetime.utcnow()
@ -118,7 +116,7 @@ def make(apps, sortedids, apks, repodir, archive):
if mirror is not None:
mirrors.append(mirror + '/')
if mirrorcheckfailed:
sys.exit(1)
raise FDroidException("Malformed repository mirrors.")
if mirrors:
repodict['mirrors'] = mirrors
@ -364,9 +362,8 @@ def make_v0(apps, apks, repodir, repodict, requestsdict):
# Check for duplicates - they will make the client unhappy...
for i in range(len(apklist) - 1):
if apklist[i]['versionCode'] == apklist[i + 1]['versionCode']:
logging.critical("duplicate versions: '%s' - '%s'" % (
raise FDroidException("duplicate versions: '%s' - '%s'" % (
apklist[i]['apkName'], apklist[i + 1]['apkName']))
sys.exit(1)
current_version_code = 0
current_version_file = None
@ -475,8 +472,7 @@ def make_v0(apps, apks, repodir, repodict, requestsdict):
jar_output = 'index_unsigned.jar' if common.options.nosign else 'index.jar'
p = FDroidPopen(['jar', 'cf', jar_output, 'index.xml'], cwd=repodir)
if p.returncode != 0:
logging.critical("Failed to create {0}".format(jar_output))
sys.exit(1)
raise FDroidException("Failed to create {0}".format(jar_output))
# Sign the index...
signed = os.path.join(repodir, 'index.jar')
@ -513,8 +509,7 @@ def extract_pubkey():
msg = "Failed to get repo pubkey!"
if common.config['keystore'] == 'NONE':
msg += ' Is your crypto smartcard plugged in?'
logging.critical(msg)
sys.exit(1)
raise FDroidException(msg)
pubkey = p.output
repo_pubkey_fingerprint = common.get_cert_fingerprint(pubkey)
return hexlify(pubkey), repo_pubkey_fingerprint
@ -558,10 +553,6 @@ def get_mirror_service_url(url):
return '/'.join(segments)
class VerificationException(Exception):
pass
def download_repo_index(url_str, etag=None, verify_fingerprint=True):
"""
Downloads the repository index from the given :param url_str

View File

@ -28,6 +28,7 @@ from argparse import ArgumentParser
import logging
from . import common
from .exception import FDroidException
config = {}
options = None
@ -117,7 +118,7 @@ def main():
if common.test_sdk_exists(test_config):
break
if not common.test_sdk_exists(test_config):
sys.exit(3)
raise FDroidException("Android SDK not found.")
if not os.path.exists('config.py'):
# 'metadata' and 'tmp' are created in fdroid
@ -135,7 +136,7 @@ def main():
else:
logging.warn('Looks like this is already an F-Droid repo, cowardly refusing to overwrite it...')
logging.info('Try running `fdroid init` in an empty directory.')
sys.exit()
raise FDroidException('Repository already exists.')
if 'aapt' not in test_config or not os.path.isfile(test_config['aapt']):
# try to find a working aapt, in all the recent possible paths

View File

@ -24,7 +24,8 @@ from argparse import ArgumentParser
import logging
from . import common
from .common import SdkToolsPopen, FDroidException
from .common import SdkToolsPopen
from .exception import FDroidException
options = None
config = None

View File

@ -36,20 +36,12 @@ except ImportError:
YamlLoader = Loader
import fdroidserver.common
from fdroidserver.exception import MetaDataException
srclibs = None
warnings_action = None
class MetaDataException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def warn_or_exception(value):
'''output warning or Exception depending on -W'''
if warnings_action == 'ignore':

View File

@ -27,7 +27,8 @@ import logging
from . import common
from . import metadata
from .common import FDroidPopen, SdkToolsPopen, BuildException
from .common import FDroidPopen, SdkToolsPopen
from .exception import BuildException
config = None
options = None

View File

@ -24,7 +24,7 @@ import logging
from . import common
from . import metadata
from .common import BuildException, VCSException
from .exception import BuildException, VCSException
config = None
options = None

View File

@ -30,6 +30,7 @@ import logging
import shutil
from . import common
from .exception import FDroidException
config = None
options = None
@ -97,7 +98,7 @@ def update_awsbucket_s3cmd(repo_section):
'--exclude', indexjar,
'--exclude', indexv1jar,
repo_section, s3url]) != 0:
sys.exit(1)
raise FDroidException()
logging.debug('s3cmd sync all files in ' + repo_section + ' to ' + s3url)
if subprocess.call(s3cmdargs +
['--no-check-md5',
@ -105,7 +106,7 @@ def update_awsbucket_s3cmd(repo_section):
'--exclude', indexjar,
'--exclude', indexv1jar,
repo_section, s3url]) != 0:
sys.exit(1)
raise FDroidException()
logging.debug('s3cmd sync indexes ' + repo_section + ' to ' + s3url + ' and delete')
s3cmdargs.append('--delete-removed')
@ -115,7 +116,7 @@ def update_awsbucket_s3cmd(repo_section):
else:
s3cmdargs.append('--check-md5')
if subprocess.call(s3cmdargs + [repo_section, s3url]) != 0:
sys.exit(1)
raise FDroidException()
def update_awsbucket_libcloud(repo_section):
@ -135,8 +136,8 @@ def update_awsbucket_libcloud(repo_section):
from libcloud.storage.providers import get_driver
if not config.get('awsaccesskeyid') or not config.get('awssecretkey'):
logging.error('To use awsbucket, you must set awssecretkey and awsaccesskeyid in config.py!')
sys.exit(1)
raise FDroidException(
'To use awsbucket, you must set awssecretkey and awsaccesskeyid in config.py!')
awsbucket = config['awsbucket']
cls = get_driver(Provider.S3)
@ -234,9 +235,9 @@ def update_serverwebroot(serverwebroot, repo_section):
['--exclude', indexxml, '--exclude', indexjar,
'--exclude', indexv1jar,
repo_section, serverwebroot]) != 0:
sys.exit(1)
raise FDroidException()
if subprocess.call(rsyncargs + [repo_section, serverwebroot]) != 0:
sys.exit(1)
raise FDroidException()
# upload "current version" symlinks if requested
if config['make_current_version_link'] and repo_section == 'repo':
links_to_upload = []
@ -246,7 +247,7 @@ def update_serverwebroot(serverwebroot, repo_section):
links_to_upload.append(f)
if len(links_to_upload) > 0:
if subprocess.call(rsyncargs + links_to_upload + [serverwebroot]) != 0:
sys.exit(1)
raise FDroidException()
def _local_sync(fromdir, todir):
@ -262,7 +263,7 @@ def _local_sync(fromdir, todir):
rsyncargs += ['--quiet']
logging.debug(' '.join(rsyncargs + [fromdir, todir]))
if subprocess.call(rsyncargs + [fromdir, todir]) != 0:
sys.exit(1)
raise FDroidException()
def sync_from_localcopy(repo_section, local_copy_dir):

View File

@ -16,13 +16,13 @@
# 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/>.
import sys
import os
import zipfile
from argparse import ArgumentParser
import logging
from . import common
from .exception import FDroidException
config = None
options = None
@ -53,8 +53,7 @@ def sign_jar(jar):
}
p = common.FDroidPopen(args, envs=env_vars)
if p.returncode != 0:
logging.critical("Failed to sign %s!" % jar)
sys.exit(1)
raise FDroidException("Failed to sign %s!" % jar)
def sign_index_v1(repodir, json_name):
@ -87,8 +86,8 @@ def main():
config = common.read_config(options)
if 'jarsigner' not in config:
logging.critical('Java jarsigner not found! Install in standard location or set java_paths!')
sys.exit(1)
raise FDroidException(
'Java jarsigner not found! Install in standard location or set java_paths!')
repodirs = ['repo']
if config['archive_older'] != 0:
@ -97,8 +96,7 @@ def main():
signed = 0
for output_dir in repodirs:
if not os.path.isdir(output_dir):
logging.error("Missing output directory '" + output_dir + "'")
sys.exit(1)
raise FDroidException("Missing output directory '" + output_dir + "'")
unsigned = os.path.join(output_dir, 'index_unsigned.jar')
if os.path.exists(unsigned):

View File

@ -41,7 +41,8 @@ from . import btlog
from . import common
from . import index
from . import metadata
from .common import BuildException, SdkToolsPopen
from .common import SdkToolsPopen
from .exception import BuildException, FDroidException
METADATA_VERSION = 18
@ -820,8 +821,7 @@ def scan_repo_files(apkcache, repodir, knownapks, use_date_from_file=False):
continue
stat = os.stat(filename)
if stat.st_size == 0:
logging.error(filename + ' is zero size!')
sys.exit(1)
raise FDroidException(filename + ' is zero size!')
shasum = sha256sum(filename)
usecache = False
@ -897,7 +897,7 @@ def scan_apk_aapt(apk, apkfile):
logging.error("Could not find {0} to remove it".format(apkfile))
else:
logging.error("Failed to get apk information, skipping " + apkfile)
raise BuildException("Invaild APK")
raise BuildException("Invalid APK")
for line in p.output.splitlines():
if line.startswith("package:"):
try:
@ -905,9 +905,7 @@ def scan_apk_aapt(apk, apkfile):
apk['versionCode'] = int(re.match(APK_VERCODE_PAT, line).group(1))
apk['versionName'] = re.match(APK_VERNAME_PAT, line).group(1)
except Exception as e:
logging.error("Package matching failed: " + str(e))
logging.info("Line was: " + line)
sys.exit(1)
raise FDroidException("Package matching failed: " + str(e) + "\nLine was: " + line)
elif line.startswith("application:"):
apk['name'] = re.match(APK_LABEL_PAT, line).group(1)
# Keep path to non-dpi icon in case we need it
@ -1000,11 +998,10 @@ def scan_apk_androguard(apk, apkfile):
logging.error("Failed to get apk information, skipping " + apkfile)
raise BuildException("Invaild APK")
except ImportError:
logging.critical("androguard library is not installed and aapt not present")
sys.exit(1)
raise FDroidException("androguard library is not installed and aapt not present")
except FileNotFoundError:
logging.error("Could not open apk file for analysis")
raise BuildException("Invaild APK")
raise BuildException("Invalid APK")
apk['packageName'] = apkobject.get_package()
apk['versionCode'] = int(apkobject.get_androidversion_code())
@ -1508,8 +1505,7 @@ def main():
config = common.read_config(options)
if not ('jarsigner' in config and 'keytool' in config):
logging.critical('Java JDK not found! Install in standard location or set java_paths!')
sys.exit(1)
raise FDroidException('Java JDK not found! Install in standard location or set java_paths!')
repodirs = ['repo']
if config['archive_older'] != 0:

View File

@ -25,7 +25,7 @@ import logging
from . import common
from . import net
from .common import FDroidException
from .exception import FDroidException
options = None
config = None
@ -80,7 +80,7 @@ def main():
try:
net.download_file(url, dldir=tmp_dir)
except requests.exceptions.HTTPError as e:
raise FDroidException('downloading %s failed', url) from e
raise FDroidException('Downloading %s failed. %s', (url, e))
compare_result = common.verify_apks(
remoteapk,