Compare commits
13 Commits
8724ca2ba1
...
a1f5713ebd
Author | SHA1 | Date |
---|---|---|
Jochen Sprickerhof | a1f5713ebd | |
Hans-Christoph Steiner | 32ef77ecb6 | |
Hans-Christoph Steiner | be59b38ac1 | |
Hans-Christoph Steiner | ef4ec74882 | |
Hans-Christoph Steiner | 1c84f63247 | |
Hans-Christoph Steiner | 5b7abc0423 | |
Hans-Christoph Steiner | 7a144a4762 | |
Hans-Christoph Steiner | cdc7c98707 | |
Hans-Christoph Steiner | a742df3758 | |
Hans-Christoph Steiner | e45e37b2df | |
Michael Pöhn | 005a33732c | |
Michael Pöhn | bd6afa4365 | |
Jochen Sprickerhof | 769ef07536 |
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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']:
|
||||
|
|
|
@ -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!'))
|
||||
|
|
2
setup.py
2
setup.py
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue