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