Add sideload command
The sideload command runs the supplied names through the pmbootstrap buildsystem to make sure they're up-to-date, then uses scp from the host to copy the built apks to /tmp on the phone and installs them through ssh. If the --install-key option is set then it will also copy over the apk key that's used for signing the packages built by pmbootstrap in case the postmarketOS install on the device isn't build by the same machine as you're sideloading from.
This commit is contained in:
parent
5cbde81842
commit
1921fc5f27
|
@ -478,7 +478,7 @@ def package(args, pkgname, arch=None, force=False, strict=False,
|
|||
|
||||
:param pkgname: package name to be built, as specified in the APKBUILD
|
||||
:param arch: architecture we're building for (default: native)
|
||||
:param force: even build, if not necessary
|
||||
:param force: allways build, even if not necessary
|
||||
:param strict: avoid building with irrelevant dependencies installed by
|
||||
letting abuild install and uninstall all dependencies.
|
||||
:param skip_init_buildenv: can be set to False to avoid initializing the
|
||||
|
|
|
@ -616,3 +616,8 @@ newapkbuild_arguments_switches_other = [
|
|||
#
|
||||
# Patterns of package names to ignore for automatic pmaport upgrading ("pmbootstrap aportupgrade --all")
|
||||
upgrade_ignore = ["device-*", "firmware-*", "linux-*", "postmarketos-*", "*-aarch64", "*-armhf", "*-armv7"]
|
||||
|
||||
#
|
||||
# SIDELOAD
|
||||
#
|
||||
sideload_sudo_prompt = "[sudo] password for %u@%h: "
|
||||
|
|
|
@ -9,6 +9,7 @@ import sys
|
|||
import pmb.aportgen
|
||||
import pmb.build
|
||||
import pmb.build.autodetect
|
||||
import pmb.sideload
|
||||
import pmb.chroot
|
||||
import pmb.chroot.initfs
|
||||
import pmb.chroot.other
|
||||
|
@ -113,6 +114,15 @@ def checksum(args):
|
|||
pmb.build.checksum.update(args, package)
|
||||
|
||||
|
||||
def sideload(args):
|
||||
arch = args.deviceinfo["arch"]
|
||||
if args.arch:
|
||||
arch = args.arch
|
||||
user = args.user
|
||||
host = args.host
|
||||
pmb.sideload.sideload(args, user, host, arch, args.install_key, args.packages)
|
||||
|
||||
|
||||
def chroot(args):
|
||||
# Suffix
|
||||
suffix = _parse_suffix(args)
|
||||
|
|
|
@ -135,6 +135,23 @@ def arguments_export(subparser):
|
|||
return ret
|
||||
|
||||
|
||||
def arguments_sideload(subparser):
|
||||
ret = subparser.add_parser("sideload", help="Push packages to a running"
|
||||
" phone connected over usb or wifi")
|
||||
add_packages_arg(ret, nargs="+")
|
||||
ret.add_argument("--host", help="ip of the device over wifi"
|
||||
" (defaults to 172.16.42.1)",
|
||||
default="172.16.42.1")
|
||||
ret.add_argument("--user", help="use a different username than the"
|
||||
" one set in init")
|
||||
ret.add_argument("--arch", help="use a different architecture than the one"
|
||||
" set in init")
|
||||
ret.add_argument("--install-key", help="install the apk key from this"
|
||||
" machine if needed",
|
||||
action="store_true", dest="install_key")
|
||||
return ret
|
||||
|
||||
|
||||
def arguments_flasher(subparser):
|
||||
ret = subparser.add_parser("flasher", help="flash something to the"
|
||||
" target device")
|
||||
|
@ -533,6 +550,7 @@ def arguments():
|
|||
arguments_repo_missing(sub)
|
||||
arguments_kconfig(sub)
|
||||
arguments_export(sub)
|
||||
arguments_sideload(sub)
|
||||
arguments_flasher(sub)
|
||||
arguments_initfs(sub)
|
||||
arguments_qemu(sub)
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
# Copyright 2020 Martijn Braam
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
import glob
|
||||
import os
|
||||
import logging
|
||||
|
||||
import pmb.helpers.run
|
||||
import pmb.parse.apkindex
|
||||
import pmb.config.pmaports
|
||||
import pmb.build
|
||||
|
||||
|
||||
def scp_abuild_key(args, user, host):
|
||||
""" Copy the building key of the local installation to the target device,
|
||||
so it trusts the apks that were signed here.
|
||||
:param user: target device ssh username
|
||||
:param host: target device ssh hostname """
|
||||
|
||||
keys = glob.glob(os.path.join(args.work, "config_abuild", "*.pub"))
|
||||
key = keys[0]
|
||||
key_name = os.path.basename(key)
|
||||
|
||||
logging.info(f"Copying signing key ({key_name}) to {user}@{host}")
|
||||
command = ['scp', key, f'{user}@{host}:/tmp']
|
||||
pmb.helpers.run.user(args, command, output="interactive")
|
||||
|
||||
logging.info(f"Installing signing key at {user}@{host}")
|
||||
keyname = os.path.join("/tmp", os.path.basename(key))
|
||||
remote_cmd = ['sudo', '-p', pmb.config.sideload_sudo_prompt,
|
||||
'-S', 'mv', '-n', keyname, "/etc/apk/keys/"]
|
||||
remote_cmd = pmb.helpers.run.flat_cmd(remote_cmd)
|
||||
command = ['ssh', '-t', f'{user}@{host}', remote_cmd]
|
||||
pmb.helpers.run.user(args, command, output="tui")
|
||||
|
||||
|
||||
def ssh_install_apks(args, user, host, paths):
|
||||
""" Copy binary packages via SCP and install them via SSH.
|
||||
:param user: target device ssh username
|
||||
:param host: target device ssh hostname
|
||||
:param paths: list of absolute paths to locally stored apks
|
||||
:type paths: list """
|
||||
|
||||
remote_paths = []
|
||||
for path in paths:
|
||||
remote_paths.append(os.path.join('/tmp', os.path.basename(path)))
|
||||
|
||||
logging.info(f"Copying packages to {user}@{host}")
|
||||
command = ['scp'] + paths + [f'{user}@{host}:/tmp']
|
||||
pmb.helpers.run.user(args, command, output="interactive")
|
||||
|
||||
logging.info(f"Installing packages at {user}@{host}")
|
||||
add_cmd = ['sudo', '-p', pmb.config.sideload_sudo_prompt,
|
||||
'-S', 'apk', 'add'] + remote_paths
|
||||
add_cmd = pmb.helpers.run.flat_cmd(add_cmd)
|
||||
clean_cmd = pmb.helpers.run.flat_cmd(['rm'] + remote_paths)
|
||||
command = ['ssh', '-t', f'{user}@{host}', f'{add_cmd}; {clean_cmd}']
|
||||
pmb.helpers.run.user(args, command, output="tui")
|
||||
|
||||
|
||||
def sideload(args, user, host, arch, copy_key, pkgnames):
|
||||
""" Build packages if necessary and install them via SSH.
|
||||
|
||||
:param user: target device ssh username
|
||||
:param host: target device ssh hostname
|
||||
:param arch: target device architecture
|
||||
:param copy_key: copy the abuild key too
|
||||
:param pkgnames: list of pkgnames to be built """
|
||||
|
||||
paths = []
|
||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
||||
|
||||
for pkgname in pkgnames:
|
||||
data_repo = pmb.parse.apkindex.package(args, pkgname, arch, True)
|
||||
apk_file = f"{pkgname}-{data_repo['version']}.apk"
|
||||
host_path = os.path.join(args.work, "packages", channel, arch,
|
||||
apk_file)
|
||||
if not os.path.isfile(host_path):
|
||||
pmb.build.package(args, pkgname, arch, force=True)
|
||||
|
||||
if not os.path.isfile(host_path):
|
||||
raise RuntimeError(f"The package '{pkgname}' could not be built")
|
||||
|
||||
paths.append(host_path)
|
||||
|
||||
if copy_key:
|
||||
scp_abuild_key(args, user, host)
|
||||
|
||||
ssh_install_apks(args, user, host, paths)
|
|
@ -95,6 +95,7 @@ py_files="
|
|||
pmb/parse/cpuinfo.py
|
||||
pmb/parse/version.py
|
||||
pmb/qemu/__init__.py
|
||||
pmb/sideload/__init__.py
|
||||
pmbootstrap.py
|
||||
test/pmb_test/__init__.py
|
||||
test/pmb_test/const.py
|
||||
|
|
Loading…
Reference in New Issue