diff --git a/pmb/flasher/__init__.py b/pmb/flasher/__init__.py index fed79cef..f5e8df18 100644 --- a/pmb/flasher/__init__.py +++ b/pmb/flasher/__init__.py @@ -19,3 +19,4 @@ along with pmbootstrap. If not, see . from pmb.flasher.init import init from pmb.flasher.run import run from pmb.flasher.frontend import frontend +from pmb.flasher.export import export diff --git a/pmb/flasher/export.py b/pmb/flasher/export.py new file mode 100644 index 00000000..ae1084b8 --- /dev/null +++ b/pmb/flasher/export.py @@ -0,0 +1,72 @@ +""" +Copyright 2017 Oliver Smith + +This file is part of pmbootstrap. + +pmbootstrap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pmbootstrap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pmbootstrap. If not, see . +""" +import logging +import os +import glob + +import pmb.build +import pmb.chroot.apk +import pmb.config +import pmb.flasher + + +def export(args, flavor, folder): + """ + Create convenience symlinks to the system image and boot files. + """ + # File descriptions + info = { + "boot.img-" + flavor: "Fastboot compatible boot.img file," + " contains initramfs and kernel", + "initramfs-" + flavor: "Initramfs", + "uInitrd-" + flavor: "Initramfs, legacy u-boot image format", + "vmlinuz-" + flavor: "Linux kernel", + args.device + ".img": "System partition", + } + + # Generate a list of patterns + path_native = args.work + "/chroot_native" + path_boot = args.work + "/chroot_rootfs_" + args.device + "/boot" + patterns = [path_boot + "/*-" + flavor, + path_native + "/home/user/rootfs/" + args.device + ".img"] + + # Generate a list of files from the patterns + files = [] + for pattern in patterns: + files += glob.glob(pattern) + + # Iterate through all files + for file in files: + basename = os.path.basename(file) + link = folder + "/" + basename + + # Display a readable message + msg = "Symlink: " + basename + if basename in info: + msg += " (" + info[basename] + ")" + logging.info(msg) + + if os.path.exists(link): + if (os.path.islink(link) and + os.path.abspath(os.readlink(link)) == os.path.abspath(file)): + continue + raise RuntimeError("File exists: " + link) + + # Create the symlink + pmb.helpers.run.user(args, ["ln", "-s", file, link]) diff --git a/pmb/flasher/frontend.py b/pmb/flasher/frontend.py index 80c5fc7c..ee3a7868 100644 --- a/pmb/flasher/frontend.py +++ b/pmb/flasher/frontend.py @@ -26,26 +26,32 @@ import pmb.chroot.initfs import pmb.chroot.other -def kernel(args): +def parse_flavor_arg(args): + """ + Verify the flavor argument if specified, or return a default value. + """ # Make sure, that at least one kernel is installed suffix = "rootfs_" + args.device pmb.chroot.apk.install(args, ["device-" + args.device], suffix) - # Parse the kernel flavor + # Parse and verify the flavor argument flavor = args.flavor flavors = pmb.chroot.other.kernel_flavors_installed(args, suffix) if flavor: if flavor not in flavors: raise RuntimeError("No kernel installed with flavor " + flavor + "!" + " Run 'pmbootstrap flasher list_flavors' to get a list.") - elif not len(flavors): + return flavor + if not len(flavors): raise RuntimeError( "No kernel flavors installed in chroot " + suffix + "! Please let" " your device package depend on a package starting with 'linux-'.") - else: - flavor = flavors[0] + return flavors[0] + +def kernel(args): # Rebuild the initramfs, just to make sure (see #69) + flavor = parse_flavor_arg(args) pmb.chroot.initfs.build(args, flavor, "rootfs_" + args.device) # Generate the paths and run the flasher @@ -82,6 +88,20 @@ def list_devices(args): pmb.flasher.run(args, "list_devices") +def export(args): + # Generate system image + img_path = "/home/user/rootfs/" + args.device + ".img" + if not os.path.exists(args.work + "/chroot_native" + img_path): + setattr(args, "sdcard", None) + pmb.install.install(args, False) + + # Rebuild the initramfs, just to make sure (see #69) + flavor = parse_flavor_arg(args) + pmb.chroot.initfs.build(args, flavor, "rootfs_" + args.device) + + pmb.flasher.export(args, flavor, args.export_folder) + + def frontend(args): action = args.action_flasher if action in ["boot", "flash_kernel"]: @@ -92,3 +112,5 @@ def frontend(args): list_flavors(args) if action == "list_devices": list_devices(args) + if action == "export": + export(args) diff --git a/pmb/parse/arguments.py b/pmb/parse/arguments.py index 1988a890..d9506482 100644 --- a/pmb/parse/arguments.py +++ b/pmb/parse/arguments.py @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with pmbootstrap. If not, see . """ import argparse +import os import pmb.config import pmb.parse.arch @@ -32,12 +33,19 @@ def arguments_flasher(subparser): " inside the device rootfs chroot on this computer") sub.add_parser("list_devices", help="show connected devices") - # Boot, flash kernel + # Boot, flash kernel, export boot = sub.add_parser("boot", help="boot a kernel once") flash_kernel = sub.add_parser("flash_kernel", help="flash a kernel") - for action in [boot, flash_kernel]: + export = sub.add_parser("export", help="create convenience symlinks to the" + " generated image files (system," + " kernel, initramfs, boot.img, ...)") + for action in [boot, flash_kernel, export]: action.add_argument("--flavor", default=None) + # Export: additional arguments + export.add_argument("export_folder", help="export folder, defaults to" + " the current working directory.", + default=os.getcwd(), nargs="?") return ret @@ -199,7 +207,7 @@ def arguments(): old = getattr(args, varname) setattr(args, varname, old.replace("$WORK", args.work)) - # Add convinience shortcuts + # Add convenience shortcuts setattr(args, "arch_native", pmb.parse.arch.alpine_native()) # Add a caching dict