Compare commits

...

13 Commits

Author SHA1 Message Date
Jochen Sprickerhof a1f5713ebd Merge branch 'build_no_vcs' into 'master'
Don't check VCS for completed builds

Closes #920

See merge request fdroid/fdroidserver!1036
2024-04-27 04:19:27 +00:00
Hans-Christoph Steiner 32ef77ecb6 Merge branch 'androguard-modernization' into 'master'
port to androguard >= 4 and drop support for older than 3.3.5

See merge request fdroid/fdroidserver!1462
2024-04-25 11:09:27 +00:00
Hans-Christoph Steiner be59b38ac1 update: handle ValueError from apkInspector in androguard 4.1
androguard 4.1 uses a new lib called apkInspector instead of zipfile.ZipFile
so that it can handle usable but invalid ZIP files.  It will also throw
ValueError on some things, for example:

Traceback (most recent call last):
  File "/builds/eighthave/fdroidserver/fdroidserver-2.3a0/tests/update.TestCase", line 878, in test_scan_apk_bad_zip
    fdroidserver.update.scan_apk(apkfile)
  File "/builds/eighthave/fdroidserver/fdroidserver-2.3a0/fdroidserver/update.py", line 1586, in scan_apk
    scan_apk_androguard(apk, apk_file)
  File "/builds/eighthave/fdroidserver/fdroidserver-2.3a0/fdroidserver/update.py", line 1725, in scan_apk_androguard
    apkobject = common.get_androguard_APK(apkfile)
  File "/builds/eighthave/fdroidserver/fdroidserver-2.3a0/fdroidserver/common.py", line 2673, in get_androguard_APK
    return APK(apkfile)
  File "/usr/local/lib/python3.10/dist-packages/androguard/core/apk/__init__.py", line 273, in __init__
    self.zip = ZipEntry.parse(filename, False)
  File "/usr/local/lib/python3.10/dist-packages/apkInspector/headers.py", line 410, in parse
    eocd = EndOfCentralDirectoryRecord.parse(apk_file)
  File "/usr/local/lib/python3.10/dist-packages/apkInspector/headers.py", line 59, in parse
    raise ValueError("End of central directory record (EOCD) signature not found")
ValueError: End of central directory record (EOCD) signature not found
2024-04-25 13:00:23 +02:00
Hans-Christoph Steiner ef4ec74882 some parts of androguard 4.x use loguru instead of logging 2024-04-25 12:39:12 +02:00
Hans-Christoph Steiner 1c84f63247 replace deprecated get_element() which was removed in 4.x
/usr/lib/python3/dist-packages/androguard/core/bytecodes/apk.py:884: DeprecationWarning: This method is deprecated since 3.3.5.

It was added in 3.3.5.  Debian/bullseye and Ubuntu/20.04/focal both include
new enough versions.  Debian/buster's is too old (3.3.3).
2024-04-25 12:39:12 +02:00
Hans-Christoph Steiner 5b7abc0423 single function to tame androguard's verbose default output
# Conflicts:
#	fdroidserver/common.py
2024-04-25 12:39:12 +02:00
Hans-Christoph Steiner 7a144a4762 port to androguard >= 4 and drop support for older than 3.3.3
This also makes androguard a hard requirement, which has been true for a
while anyway.  So the code that handles androguard as an optional
requirement is removed.  androguard from Debian/buster is new enough, so
this does not seem like it will cause any problems.
2024-04-25 12:39:12 +02:00
Hans-Christoph Steiner cdc7c98707 common.get_androguard_APK() is no longer private to the module 2024-04-25 12:39:12 +02:00
Hans-Christoph Steiner a742df3758
add CHANGELOG entry for v2.2.2 2024-04-25 12:39:00 +02:00
Hans-Christoph Steiner e45e37b2df Merge branch 'altstore-index-fix' into 'master'
🐛 index fix: skip altstore when no IPAs present

See merge request fdroid/fdroidserver!1473
2024-04-24 12:05:03 +00:00
Michael Pöhn 005a33732c apply review suggestions 2024-04-24 11:56:07 +00:00
Michael Pöhn bd6afa4365
🐛 index fix: skip altstore when no IPAs present 2024-04-24 12:45:29 +02:00
Jochen Sprickerhof 769ef07536
Don't check VCS for completed builds
This speeds up the build a lot.
2024-04-08 14:46:30 +02:00
12 changed files with 185 additions and 181 deletions

View File

@ -15,6 +15,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* The `maven:` field is now always a string, with `yes` as a legacy special
value. It is no longer treated like a boolean in any case.
## [2.2.2] - 2024-04-24
### Added
* Include sdkmanager as dep in setup.py for Homebrew package.
https://github.com/Homebrew/homebrew-core/pull/164510
## [2.2.1] - 2023-03-09
### Added

View File

@ -53,7 +53,7 @@ ssh_channel = None
# Note that 'force' here also implies test mode.
def build_server(app, build, vcs, build_dir, output_dir, log_dir, force):
def build_server(app, build, output_dir, log_dir, force, refresh):
"""Do a build on the builder vm.
Parameters
@ -61,10 +61,6 @@ def build_server(app, build, vcs, build_dir, output_dir, log_dir, force):
app
app metadata dict
build
vcs
version control system controller object
build_dir
local source-code checkout of app
output_dir
target folder for the build result
force
@ -194,10 +190,6 @@ def build_server(app, build, vcs, build_dir, output_dir, log_dir, force):
srclibpaths.append(
common.getsrclib(lib, 'build/srclib', basepath=True, prepare=False))
# If one was used for the main source, add that too.
basesrclib = vcs.getsrclib()
if basesrclib:
srclibpaths.append(basesrclib)
for name, number, lib in srclibpaths:
logging.info("Sending srclib '%s'" % lib)
ftp.chdir(posixpath.join(homedir, 'build', 'srclib'))
@ -214,9 +206,19 @@ def build_server(app, build, vcs, build_dir, output_dir, log_dir, force):
else:
raise BuildException(_('cannot find required srclibs: "{path}"')
.format(path=srclibsfile))
vcs, build_dir = common.setup_vcs(app)
# When using server mode, still keep a local cache of the repo, by
# grabbing the source now.
vcs.gotorevision(build.commit, refresh)
# Initialise submodules if required
if build.submodules:
vcs.initsubmodules()
# Copy the main app source code
# (no need if it's a srclib)
if (not basesrclib) and os.path.exists(build_dir):
if os.path.exists(build_dir):
ftp.chdir(posixpath.join(homedir, 'build'))
fv = '.fdroidvcs-' + app.id
ftp.put(os.path.join('build', fv), fv)
@ -361,7 +363,7 @@ def get_metadata_from_apk(app, build, apkfile):
return versionCode, versionName
def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, extlib_dir, tmp_dir, force, onserver, refresh):
def build_local(app, build, output_dir, log_dir, srclib_dir, extlib_dir, tmp_dir, force, onserver, refresh):
"""Do a build locally."""
ndk_path = build.ndk_path()
if build.ndk or (build.buildjni and build.buildjni != ['no']):
@ -414,6 +416,7 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext
% (app.id, build.versionName, build.sudo))
# Prepare the source code...
vcs, build_dir = common.setup_vcs(app)
root_dir, srclibpaths = common.prepare_source(vcs, app, build,
build_dir, srclib_dir,
extlib_dir, onserver, refresh)
@ -759,8 +762,8 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext
os.path.join(output_dir, tarname))
def trybuild(app, build, build_dir, output_dir, log_dir, also_check_dir,
srclib_dir, extlib_dir, tmp_dir, repo_dir, vcs, test,
def trybuild(app, build, output_dir, log_dir, also_check_dir,
srclib_dir, extlib_dir, tmp_dir, repo_dir, test,
server, force, onserver, refresh):
"""Build a particular version of an application, if it needs building.
@ -806,17 +809,9 @@ def trybuild(app, build, build_dir, output_dir, log_dir, also_check_dir,
build.versionName, build.versionCode, app.id))
if server:
# When using server mode, still keep a local cache of the repo, by
# grabbing the source now.
vcs.gotorevision(build.commit, refresh)
# Initialise submodules if required
if build.submodules:
vcs.initsubmodules()
build_server(app, build, vcs, build_dir, output_dir, log_dir, force)
build_server(app, build, output_dir, log_dir, force, refresh)
else:
build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, extlib_dir, tmp_dir, force, onserver, refresh)
build_local(app, build, output_dir, log_dir, srclib_dir, extlib_dir, tmp_dir, force, onserver, refresh)
return True
@ -1024,9 +1019,6 @@ def main():
endtime = time.time() + 72 * 60 * 60
max_build_time_reached = False
for appid, app in apps.items():
first = True
for build in app.get('Builds', []):
if time.time() > endtime:
max_build_time_reached = True
@ -1047,18 +1039,10 @@ def main():
tools_version_log = ''
try:
# For the first build of a particular app, we need to set up
# the source repo. We can reuse it on subsequent builds, if
# there are any.
if first:
vcs, build_dir = common.setup_vcs(app)
first = False
logging.debug("Checking %s:%s" % (appid, build.versionCode))
if trybuild(app, build, build_dir, output_dir, log_dir,
if trybuild(app, build, output_dir, log_dir,
also_check_dir, srclib_dir, extlib_dir,
tmp_dir, repo_dir, vcs, options.test,
tmp_dir, repo_dir, options.test,
options.server, options.force,
options.onserver, options.refresh):
toolslog = os.path.join(log_dir,

View File

@ -1149,7 +1149,6 @@ class vcs:
self.local = local
self.clone_failed = False
self.refreshed = False
self.srclib = None
def _gettags(self):
raise NotImplementedError
@ -1258,10 +1257,6 @@ class vcs:
"""Get current commit reference (hash, revision, etc)."""
raise VCSException('getref not supported for this vcs type')
def getsrclib(self):
"""Return the srclib (name, path) used in setting up the current revision, or None."""
return self.srclib
class vcs_git(vcs):
@ -2296,11 +2291,6 @@ def prepare_source(vcs, app, build, build_dir, srclib_dir, extlib_dir, onserver=
for name, number, libpath in srclibpaths:
place_srclib(root_dir, int(number) if number else None, libpath)
basesrclib = vcs.getsrclib()
# If one was used for the main source, add that too.
if basesrclib:
srclibpaths.append(basesrclib)
# Update the local.properties file
localprops = [os.path.join(build_dir, 'local.properties')]
if build.subdir:
@ -2629,29 +2619,46 @@ def get_file_extension(filename):
return os.path.splitext(filename)[1].lower()[1:]
def use_androguard():
"""Report if androguard is available, and config its debug logging."""
def _androguard_logging_level(level=logging.ERROR):
"""Tames androguard's default debug output.
There should be no debug output when the functions are being used
via the API. Otherwise, the output is controlled by the --verbose
flag.
To get coverage across the full range of androguard >= 3.3.5, this
includes all known logger names that are relevant. So some of
these names might not be present in the version of androguard
currently in use.
"""
if options and options.verbose:
level = logging.WARNING
for name in (
'androguard.apk',
'androguard.axml',
'androguard.core.api_specific_resources',
'androguard.core.apk',
'androguard.core.axml',
):
logging.getLogger(name).setLevel(level)
# some parts of androguard 4.x use loguru instead of logging
try:
import androguard
if use_androguard.show_path:
logging.debug(_('Using androguard from "{path}"').format(path=androguard.__file__))
use_androguard.show_path = False
if options and options.verbose:
logging.getLogger("androguard.axml").setLevel(logging.INFO)
logging.getLogger("androguard.core.api_specific_resources").setLevel(logging.ERROR)
return True
from loguru import logger
logger.remove()
except ImportError:
return False
pass
use_androguard.show_path = True # type: ignore
def _get_androguard_APK(apkfile):
def get_androguard_APK(apkfile):
try:
# these were moved in androguard 4.0
from androguard.core.apk import APK
except ImportError:
from androguard.core.bytecodes.apk import APK
except ImportError as exc:
raise FDroidException("androguard library is not installed") from exc
_androguard_logging_level()
return APK(apkfile)
@ -2693,7 +2700,13 @@ def is_debuggable_or_testOnly(apkfile):
"""
if get_file_extension(apkfile) != 'apk':
return False
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG
try:
# these were moved in androguard 4.0
from androguard.core.axml import AXMLParser, format_value, START_TAG
except ImportError:
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG
_androguard_logging_level()
with ZipFile(apkfile) as apk:
with apk.open('AndroidManifest.xml') as manifest:
axml = AXMLParser(manifest.read())
@ -2753,12 +2766,20 @@ def get_apk_id_androguard(apkfile):
versionName is set to a Android String Resource (e.g. an integer
hex value that starts with @).
This function is part of androguard as get_apkid(), so this
vendored and modified to return versionCode as an integer.
"""
if not os.path.exists(apkfile):
raise FDroidException(_("Reading packageName/versionCode/versionName failed, APK invalid: '{apkfilename}'")
.format(apkfilename=apkfile))
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
try:
# these were moved in androguard 4.0
from androguard.core.axml import AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
except ImportError:
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
_androguard_logging_level()
appid = None
versionCode = None
@ -2793,7 +2814,7 @@ def get_apk_id_androguard(apkfile):
.format(path=apkfile))
if not versionName or versionName[0] == '@':
a = _get_androguard_APK(apkfile)
a = get_androguard_APK(apkfile)
versionName = ensure_final_value(a.package, a.get_android_resources(), a.get_androidversion_name())
if not versionName:
versionName = '' # versionName is expected to always be a str
@ -3159,8 +3180,8 @@ def get_first_signer_certificate(apkpath):
elif len(cert_files) == 1:
cert_encoded = get_certificate(apk.read(cert_files[0]))
if not cert_encoded and use_androguard():
apkobject = _get_androguard_APK(apkpath)
if not cert_encoded:
apkobject = get_androguard_APK(apkpath)
certs = apkobject.get_certificates_der_v2()
if len(certs) > 0:
logging.debug(_('Using APK Signature v2'))

View File

@ -1766,6 +1766,10 @@ def make_altstore(apps, apks, config, repodir, pretty=False):
https://faq.altstore.io/distribute-your-apps/make-a-source
https://faq.altstore.io/distribute-your-apps/updating-apps
"""
if not any(Path(repodir).glob('*.ipa')):
# no IPA files present in repo, nothing to do here, exiting early
return
indent = 2 if pretty else None
# for now alt-store support is english only
for lang in ['en']:

View File

@ -1722,8 +1722,7 @@ def _sanitize_sdk_version(value):
def scan_apk_androguard(apk, apkfile):
try:
from androguard.core.bytecodes.apk import APK
apkobject = APK(apkfile)
apkobject = common.get_androguard_APK(apkfile)
if apkobject.is_valid_APK():
arsc = apkobject.get_android_resources()
else:
@ -1739,7 +1738,7 @@ def scan_apk_androguard(apk, apkfile):
logging.error(_("Failed to get APK information, skipping {path}")
.format(path=apkfile))
raise BuildException(_("Invalid APK"))
except (FileNotFoundError, zipfile.BadZipFile) as e:
except (FileNotFoundError, ValueError, zipfile.BadZipFile) as e:
logging.error(_("Could not open APK {path} for analysis: ").format(path=apkfile)
+ str(e))
raise BuildException(_("Invalid APK")) from e
@ -1779,7 +1778,7 @@ def scan_apk_androguard(apk, apkfile):
if maxSdkVersion is not None:
apk['maxSdkVersion'] = maxSdkVersion
icon_id_str = apkobject.get_element("application", "icon")
icon_id_str = apkobject.get_attribute_value("application", "icon")
if icon_id_str:
try:
icon_id = int(icon_id_str.replace("@", "0x"), 16)
@ -2581,7 +2580,6 @@ def main():
config = common.read_config(options)
common.setup_status_output(start_timestamp)
common.use_androguard()
if not (('jarsigner' in config or 'apksigner' in config)
and 'keytool' in config):
raise FDroidException(_('Java JDK not found! Install in standard location or set java_paths!'))

View File

@ -92,7 +92,7 @@ setup(
],
install_requires=[
'appdirs',
'androguard >= 3.1.0, != 3.3.0, != 3.3.1, != 3.3.2, <4',
'androguard >= 3.3.5',
'clint',
'defusedxml',
'GitPython',

View File

@ -49,8 +49,6 @@ class BuildTest(unittest.TestCase):
def setUp(self):
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('androguard.axml')
logger.setLevel(logging.INFO) # tame the axml debug messages
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir)
fdroidserver.common.config = None
@ -223,6 +221,7 @@ class BuildTest(unittest.TestCase):
@mock.patch('fdroidserver.build.FDroidPopen')
@mock.patch('fdroidserver.common.is_debuggable_or_testOnly', lambda f: False)
@mock.patch('fdroidserver.common.get_native_code', lambda f: 'x86')
@mock.patch('fdroidserver.common.setup_vcs', lambda f: (mock.Mock(), "."))
def test_build_local_maven(self, fake_FDroidPopen, fake_get_apk_id):
"""Test build_local() with a maven project"""
@ -258,14 +257,11 @@ class BuildTest(unittest.TestCase):
build.versionCode,
build.versionName,
)
vcs = mock.Mock()
build.maven = 'yes@..'
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=self.testdir,
output_dir=self.testdir,
log_dir=os.getcwd(),
srclib_dir=None,
@ -280,8 +276,6 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=self.testdir,
output_dir=self.testdir,
log_dir=os.getcwd(),
srclib_dir=None,
@ -316,7 +310,6 @@ class BuildTest(unittest.TestCase):
build.ndk = 'r21e' # aka 21.4.7075529
ndk_version = '21.4.7075529'
ndk_dir = Path(config['sdk_path']) / 'ndk' / ndk_version
vcs = mock.Mock()
def make_fake_apk(output, build):
with open(build.output, 'w') as fp:
@ -348,6 +341,8 @@ class BuildTest(unittest.TestCase):
'fdroidserver.build.FDroidPopen', FakeProcess
) as _ignored, mock.patch(
'sdkmanager.install', wraps=fake_sdkmanager_install
) as _ignored, mock.patch(
'fdroidserver.common.setup_vcs', return_value=(mock.Mock(), testdir)
) as _ignored:
_ignored # silence the linters
with self.assertRaises(
@ -357,8 +352,6 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=testdir,
output_dir=testdir,
log_dir=None,
srclib_dir=None,
@ -376,8 +369,6 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=testdir,
output_dir=testdir,
log_dir=os.getcwd(),
srclib_dir=None,
@ -400,6 +391,7 @@ class BuildTest(unittest.TestCase):
'fdroidserver.common.sha256sum',
lambda f: 'ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e',
)
@mock.patch('fdroidserver.common.setup_vcs', lambda f: (mock.Mock(), "."))
def test_build_local_ndk_some_installed(self):
"""Test if `fdroid build` detects installed NDKs and auto-installs when missing"""
with tempfile.TemporaryDirectory() as testdir, TmpCwd(
@ -427,7 +419,6 @@ class BuildTest(unittest.TestCase):
build.ndk = 'r21e' # aka 21.4.7075529
ndk_version = '21.4.7075529'
ndk_dir = Path(config['sdk_path']) / 'ndk' / ndk_version
vcs = mock.Mock()
def make_fake_apk(output, build):
with open(build.output, 'w') as fp:
@ -457,8 +448,6 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=testdir,
output_dir=testdir,
log_dir=os.getcwd(),
srclib_dir=None,
@ -492,7 +481,6 @@ class BuildTest(unittest.TestCase):
build.scanignore = ['foo.aar']
build.versionCode = 1
build.versionName = '1.0'
vcs = mock.Mock()
os.mkdir('reports')
os.mkdir('target')
@ -525,30 +513,31 @@ class BuildTest(unittest.TestCase):
fp.write('APK PLACEHOLDER')
return output
with mock.patch('fdroidserver.common.replace_build_vars', wraps=make_fake_apk):
with mock.patch('fdroidserver.common.get_native_code', return_value='x86'):
with mock.patch(
'fdroidserver.common.get_apk_id',
return_value=(app.id, build.versionCode, build.versionName),
):
with mock.patch(
'fdroidserver.common.is_debuggable_or_testOnly',
return_value=False,
):
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=self.testdir,
output_dir=self.testdir,
log_dir=None,
srclib_dir=None,
extlib_dir=None,
tmp_dir=None,
force=False,
onserver=False,
refresh=False,
)
with mock.patch(
'fdroidserver.common.replace_build_vars', wraps=make_fake_apk
) as _ignored, mock.patch(
'fdroidserver.common.get_native_code', return_value='x86'
) as _ignored, mock.patch(
'fdroidserver.common.get_apk_id',
return_value=(app.id, build.versionCode, build.versionName),
) as _ignored, mock.patch(
'fdroidserver.common.is_debuggable_or_testOnly', return_value=False
) as _ignored, mock.patch(
'fdroidserver.common.setup_vcs', return_value=(mock.Mock(), self.testdir)
) as _ignored:
_ignored # silence the linters
fdroidserver.build.build_local(
app,
build,
output_dir=self.testdir,
log_dir=None,
srclib_dir=None,
extlib_dir=None,
tmp_dir=None,
force=False,
onserver=False,
refresh=False,
)
self.assertTrue(os.path.exists('foo.aar'))
self.assertTrue(os.path.isdir('build'))
@ -883,8 +872,6 @@ class BuildTest(unittest.TestCase):
}
fdroidserver.common.config = {'sdk_path': '/fake/android/sdk/path'}
fdroidserver.build.options = mock.MagicMock()
vcs = mock.Mock()
vcs.getsrclib = mock.Mock(return_value=None)
app = fdroidserver.metadata.App()
app['metadatapath'] = 'metadata/fake.id.yml'
app['id'] = 'fake.id'
@ -899,29 +886,33 @@ class BuildTest(unittest.TestCase):
)
app['Builds'] = [build]
test_flag = ('--on-server', True)
fdroidserver.build.build_server(app, build, vcs, '', '', '', False)
self.assertTrue(fdroidserver_vmtools_get_build_vm.called)
with mock.patch(
'fdroidserver.common.setup_vcs', return_value=(mock.Mock(), "")
) as _ignored:
_ignored # silence the linters
test_flag = ('--on-server', True)
fdroidserver.build.build_server(app, build, '', '', False, False)
self.assertTrue(fdroidserver_vmtools_get_build_vm.called)
for force in (True, False):
test_flag = ('--force', force)
fdroidserver.build.build_server(app, build, vcs, '', '', '', force)
for force in (True, False):
test_flag = ('--force', force)
fdroidserver.build.build_server(app, build, '', '', force, False)
fdroidserver.build.options.notarball = True
test_flag = ('--no-tarball', True)
fdroidserver.build.build_server(app, build, vcs, '', '', '', False)
fdroidserver.build.options.notarball = False
test_flag = ('--no-tarball', False)
fdroidserver.build.build_server(app, build, vcs, '', '', '', False)
fdroidserver.build.options.notarball = True
test_flag = ('--no-tarball', True)
fdroidserver.build.build_server(app, build, '', '', False, False)
fdroidserver.build.options.notarball = False
test_flag = ('--no-tarball', False)
fdroidserver.build.build_server(app, build, '', '', False, False)
fdroidserver.build.options.skipscan = False
test_flag = ('--scan-binary', True)
fdroidserver.build.build_server(app, build, vcs, '', '', '', False)
fdroidserver.build.options.skipscan = True
test_flag = ('--scan-binary', False)
fdroidserver.build.build_server(app, build, vcs, '', '', '', False)
test_flag = ('--skip-scan', True)
fdroidserver.build.build_server(app, build, vcs, '', '', '', False)
fdroidserver.build.options.skipscan = False
test_flag = ('--scan-binary', True)
fdroidserver.build.build_server(app, build, '', '', False, False)
fdroidserver.build.options.skipscan = True
test_flag = ('--scan-binary', False)
fdroidserver.build.build_server(app, build, '', '', False, False)
test_flag = ('--skip-scan', True)
fdroidserver.build.build_server(app, build, '', '', False, False)
@mock.patch('fdroidserver.vmtools.get_build_vm')
@mock.patch('fdroidserver.vmtools.get_clean_builder')
@ -932,6 +923,7 @@ class BuildTest(unittest.TestCase):
@mock.patch('fdroidserver.build.build_local')
@mock.patch('fdroidserver.common.get_android_tools_version_log', lambda: 'versions')
@mock.patch('fdroidserver.common.deploy_build_log_with_rsync', lambda a, b, c: None)
@mock.patch('fdroidserver.common.setup_vcs', lambda f: (mock.Mock(), "."))
def test_build_server_no_local_prepare(
self,
build_build_local,
@ -1007,8 +999,6 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.options = options
fdroidserver.build.config = {'sdk_path': '/fake/android/sdk/path'}
vcs = mock.Mock()
vcs.getsrclib = mock.Mock(return_value=None)
app = fdroidserver.metadata.App()
app['metadatapath'] = 'metadata/fake.id.yml'
app['id'] = 'fake.id'
@ -1035,7 +1025,6 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.trybuild(
app,
build,
build_dir,
'unsigned',
'logs',
None,
@ -1043,7 +1032,6 @@ class BuildTest(unittest.TestCase):
extlib_dir,
'tmp',
'repo',
vcs,
options.test,
options.server,
options.force,

View File

@ -902,7 +902,7 @@ class CommonTest(unittest.TestCase):
self.assertTrue(os.path.isfile(signed))
self.assertFalse(os.path.isfile(unsigned))
self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
self.assertEqual('18', fdroidserver.common._get_androguard_APK(signed).get_min_sdk_version())
self.assertEqual('18', fdroidserver.common.get_androguard_APK(signed).get_min_sdk_version())
shutil.copy(os.path.join(self.basedir, 'minimal_targetsdk_30_unsigned.apk'), self.testdir)
unsigned = os.path.join(self.testdir, 'minimal_targetsdk_30_unsigned.apk')
@ -915,7 +915,7 @@ class CommonTest(unittest.TestCase):
self.assertFalse(os.path.isfile(unsigned))
self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
# verify it has a v2 signature
self.assertTrue(fdroidserver.common._get_androguard_APK(signed).is_signed_v2())
self.assertTrue(fdroidserver.common.get_androguard_APK(signed).is_signed_v2())
shutil.copy(os.path.join(self.basedir, 'no_targetsdk_minsdk30_unsigned.apk'), self.testdir)
unsigned = os.path.join(self.testdir, 'no_targetsdk_minsdk30_unsigned.apk')
@ -923,7 +923,7 @@ class CommonTest(unittest.TestCase):
fdroidserver.common.sign_apk(unsigned, signed, config['keyalias'])
self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
self.assertTrue(fdroidserver.common._get_androguard_APK(signed).is_signed_v2())
self.assertTrue(fdroidserver.common.get_androguard_APK(signed).is_signed_v2())
shutil.copy(os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk'), self.testdir)
unsigned = os.path.join(self.testdir, 'no_targetsdk_minsdk1_unsigned.apk')
@ -1146,11 +1146,11 @@ class CommonTest(unittest.TestCase):
"""This is a sanity test that androguard isn't broken"""
def get_minSdkVersion(apkfile):
apk = fdroidserver.common._get_androguard_APK(apkfile)
apk = fdroidserver.common.get_androguard_APK(apkfile)
return fdroidserver.common.get_min_sdk_version(apk)
def get_targetSdkVersion(apkfile):
apk = fdroidserver.common._get_androguard_APK(apkfile)
apk = fdroidserver.common.get_androguard_APK(apkfile)
return apk.get_effective_target_sdk_version()
self.assertEqual(4, get_minSdkVersion('bad-unicode-πÇÇ现代通用字-български-عربي1.apk'))

View File

@ -869,6 +869,8 @@ class AltstoreIndexTest(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
repodir = Path(tmpdir) / 'repo'
repodir.mkdir()
with open(repodir / "fake.ipa", "w") as f:
f.write("")
fdroidserver.index.make_altstore(
apps,

View File

@ -8,7 +8,9 @@ echo_header() {
get_fdroid_apk_filename() {
if [ -z $aapt ]; then
python3 -c "from androguard.core.bytecodes.apk import APK; a=APK('$1'); print(a.package+'_'+a.get_androidversion_code()+'.apk')"
appid=$(androguard apkid "$1" | sed -En 's/ +"([a-z][^"]+)",$/\1/ip')
versionCode=$(androguard apkid "$1" | sed -En 's/ +"([0-9]+)",$/\1/p')
echo "${appid}_${versionCode}.apk"
else
$aapt dump badging "$1" | sed -n "s,^package: name='\(.*\)' versionCode='\([0-9][0-9]*\)' .*,\1_\2.apk,p"
fi

View File

@ -246,7 +246,6 @@ class ScannerTest(unittest.TestCase):
build.scanignore = ['baz.so', 'foo.aar']
build.versionCode = 1
build.versionName = '1.0'
vcs = mock.Mock()
for f in ('baz.so', 'foo.aar', 'gradle-wrapper.jar'):
with open(f, 'w') as fp:
@ -269,30 +268,31 @@ class ScannerTest(unittest.TestCase):
fp.write('APK PLACEHOLDER')
return output
with mock.patch('fdroidserver.common.replace_build_vars', wraps=make_fake_apk):
with mock.patch('fdroidserver.common.get_native_code', return_value='x86'):
with mock.patch(
'fdroidserver.common.get_apk_id',
return_value=(app.id, build.versionCode, build.versionName),
):
with mock.patch(
'fdroidserver.common.is_debuggable_or_testOnly',
return_value=False,
):
fdroidserver.build.build_local(
app,
build,
vcs,
build_dir=self.testdir,
output_dir=self.testdir,
log_dir=None,
srclib_dir=None,
extlib_dir=None,
tmp_dir=None,
force=False,
onserver=False,
refresh=False,
)
with mock.patch(
'fdroidserver.common.replace_build_vars', wraps=make_fake_apk
) as _ignored, mock.patch(
'fdroidserver.common.get_native_code', return_value='x86'
) as _ignored, mock.patch(
'fdroidserver.common.get_apk_id',
return_value=(app.id, build.versionCode, build.versionName),
) as _ignored, mock.patch(
'fdroidserver.common.is_debuggable_or_testOnly', return_value=False
) as _ignored, mock.patch(
'fdroidserver.common.setup_vcs', return_value=(mock.Mock(), self.testdir)
) as _ignored:
_ignored # silence the linters
fdroidserver.build.build_local(
app,
build,
output_dir=self.testdir,
log_dir=None,
srclib_dir=None,
extlib_dir=None,
tmp_dir=None,
force=False,
onserver=False,
refresh=False,
)
self.assertTrue(os.path.exists('baz.so'))
self.assertTrue(os.path.exists('foo.aar'))
self.assertFalse(os.path.exists('gradle-wrapper.jar'))

View File

@ -5,6 +5,7 @@
import copy
import git
import glob
import hashlib
import inspect
import json
import logging
@ -20,11 +21,18 @@ import unittest
import yaml
import zipfile
import textwrap
from binascii import hexlify
from datetime import datetime
from pathlib import Path
from testcommon import TmpCwd, mkdtemp
from unittest import mock
try:
# these were moved in androguard 4.0
from androguard.core.apk import APK
except ImportError:
from androguard.core.bytecodes.apk import APK
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
@ -74,9 +82,6 @@ class UpdateTest(unittest.TestCase):
def setUp(self):
logging.basicConfig(level=logging.INFO)
logging.getLogger('androguard.apk').setLevel(logging.WARNING)
logging.getLogger('androguard.axml').setLevel(logging.INFO)
logging.getLogger('androguard.core.api_specific_resources').setLevel(logging.INFO)
from PIL import PngImagePlugin
logging.getLogger(PngImagePlugin.__name__).setLevel(logging.INFO)
@ -581,13 +586,6 @@ class UpdateTest(unittest.TestCase):
self.assertEqual(good_fingerprint, sig,
'python sig was: ' + str(sig))
# check that v1 and v2 have the same certificate
try:
import hashlib
from binascii import hexlify
from androguard.core.bytecodes.apk import APK
except ImportError:
print('WARNING: skipping rest of test since androguard is missing!')
return
apkobject = APK(apkpath)
cert_encoded = apkobject.get_certificates_der_v2()[0]
self.assertEqual(good_fingerprint, sig,