Skip to content

Commit 81d4c19

Browse files
iavclaude
andcommitted
feat(rootfs-to-image): support ROOTFS_EXPORT_DIR and configurable ROOTFS_COMPRESSION
Split the rootfs pipeline so it can produce either (or both) of: * a tarball — via ROOTFS_COMPRESSION=gzip (default, .tar.gz) / zstd (.tar.zst); matches existing behaviour, with zstd now available for faster creation and decompression on modern hardware. * an exported tree — via ROOTFS_EXPORT_DIR=<abs path>, which rsyncs the built rootfs to a host-side directory (e.g. an NFS export) without an intermediate archive. Set ROOTFS_COMPRESSION=none when only the exported tree is wanted; this skips archive creation entirely. If both ROOTFS_COMPRESSION=none and -z ROOTFS_EXPORT_DIR are set the run is aborted — otherwise the rootfs stage would produce nothing. This is infrastructure; no existing callers need to change. The netboot extension (added in a following commit) consumes ROOTFS_EXPORT_DIR to populate the NFS export tree. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a5a71c6 commit 81d4c19

1 file changed

Lines changed: 50 additions & 8 deletions

File tree

lib/functions/image/rootfs-to-image.sh

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function calculate_image_version() {
1919
calculated_image_version="${vendor_version_prelude}${BOARD^}_${RELEASE}_${BRANCH}_${kernel_version_for_image}${DESKTOP_ENVIRONMENT:+_$DESKTOP_ENVIRONMENT}${EXTRA_IMAGE_SUFFIX}"
2020
[[ $BUILD_DESKTOP == yes ]] && calculated_image_version=${calculated_image_version}_desktop
2121
[[ $BUILD_MINIMAL == yes ]] && calculated_image_version=${calculated_image_version}_minimal
22-
[[ $ROOTFS_TYPE == nfs ]] && calculated_image_version=${calculated_image_version}_nfsboot
22+
[[ $ROOTFS_TYPE == nfs || $ROOTFS_TYPE == nfs-root ]] && calculated_image_version=${calculated_image_version}_nfsboot
2323
display_alert "Calculated image version" "${calculated_image_version}" "debug"
2424
}
2525

@@ -40,7 +40,7 @@ function create_image_from_sdcard_rootfs() {
4040
if [[ ${INCLUDE_HOME_DIR:-no} == yes ]]; then exclude_home=""; fi
4141
# nilfs2 fs does not have extended attributes support, and have to be ignored on copy
4242
if [[ $ROOTFS_TYPE == nilfs2 ]]; then rsync_ea=""; fi
43-
if [[ $ROOTFS_TYPE != nfs ]]; then
43+
if [[ $ROOTFS_TYPE != nfs && $ROOTFS_TYPE != nfs-root ]]; then
4444
display_alert "Copying files via rsync to" "/ (MOUNT root)"
4545
run_host_command_logged rsync -aHWh $rsync_ea \
4646
--exclude="/boot" \
@@ -104,12 +104,54 @@ function create_image_from_sdcard_rootfs() {
104104
PRE_UMOUNT_FINAL_IMAGE
105105

106106
if [[ $ROOTFS_TYPE == nfs ]]; then
107-
display_alert "Creating rootfs archive" "rootfs.tgz" "info"
108-
tar cp --xattrs --directory=$SDCARD/ --exclude='./boot/*' --exclude='./dev/*' --exclude='./proc/*' --exclude='./run/*' --exclude='./tmp/*' \
109-
--exclude='./sys/*' $exclude_home . |
110-
pv -p -b -r -s "$(du -sb "$SDCARD"/ | cut -f1)" \
111-
-N "$(logging_echo_prefix_for_pv "create_rootfs_archive") rootfs.tgz" |
112-
gzip -c > "$DEST/images/${version}-rootfs.tgz"
107+
# ROOTFS_COMPRESSION: zstd (default, .tar.zst) | gzip (.tar.gz) | none (skip archive)
108+
declare rootfs_compression="${ROOTFS_COMPRESSION:-zstd}"
109+
declare archive_ext="" archive_filter=""
110+
case "${rootfs_compression}" in
111+
gzip) archive_ext="tar.gz"; archive_filter="gzip -c" ;;
112+
zstd | zst) archive_ext="tar.zst"; archive_filter="zstd -T0 -c" ;;
113+
none) ;;
114+
*) exit_with_error "Unknown ROOTFS_COMPRESSION: '${rootfs_compression}' (expected: gzip|zstd|none)" ;;
115+
esac
116+
if [[ "${rootfs_compression}" == "none" && -z "${ROOTFS_EXPORT_DIR}" ]]; then
117+
exit_with_error "ROOTFS_COMPRESSION=none requires ROOTFS_EXPORT_DIR (otherwise nothing is produced)"
118+
fi
119+
120+
declare -g ROOTFS_ARCHIVE_PATH=""
121+
if [[ "${rootfs_compression}" != "none" ]]; then
122+
ROOTFS_ARCHIVE_PATH="${FINALDEST}/${version}-rootfs.${archive_ext}"
123+
display_alert "Creating rootfs archive" "${version}-rootfs.${archive_ext}" "info"
124+
# Subshell with pipefail so failures in tar/pv propagate (otherwise the
125+
# exit code of the final compressor stage hides truncation mid-archive).
126+
declare -a tar_excludes=(--exclude='./boot/*' --exclude='./dev/*' --exclude='./proc/*' --exclude='./run/*' --exclude='./tmp/*' --exclude='./sys/*')
127+
[[ "${INCLUDE_HOME_DIR:-no}" != "yes" ]] && tar_excludes+=(--exclude='./home/*')
128+
(
129+
set -o pipefail
130+
tar cp --xattrs --directory="$SDCARD/" "${tar_excludes[@]}" . |
131+
pv -p -b -r -s "$(du -sb "$SDCARD"/ | cut -f1)" \
132+
-N "$(logging_echo_prefix_for_pv "create_rootfs_archive") rootfs.${archive_ext}" |
133+
${archive_filter} > "${ROOTFS_ARCHIVE_PATH}"
134+
)
135+
fi
136+
137+
# ROOTFS_EXPORT_DIR: when set, also rsync rootfs tree into this directory.
138+
# Useful when the build host is the NFS server, or has the NFS export mounted,
139+
# so netboot deployment is a single build step with no unpack/transport phase.
140+
if [[ -n "${ROOTFS_EXPORT_DIR}" ]]; then
141+
display_alert "Exporting rootfs tree" "${ROOTFS_EXPORT_DIR}" "info"
142+
run_host_command_logged mkdir -pv "${ROOTFS_EXPORT_DIR}"
143+
# --delete so files removed from the source rootfs don't survive in a
144+
# reused export tree (otherwise the NFS root silently drifts from the image).
145+
run_host_command_logged rsync -aHWh --delete $rsync_ea \
146+
--exclude="/boot/*" \
147+
--exclude="/dev/*" \
148+
--exclude="/proc/*" \
149+
--exclude="/run/*" \
150+
--exclude="/tmp/*" \
151+
--exclude="/sys/*" \
152+
$exclude_home \
153+
--info=progress0,stats1 "$SDCARD/" "${ROOTFS_EXPORT_DIR}/"
154+
fi
113155
fi
114156

115157
if [[ "${SHOW_DEBUG}" == "yes" ]]; then

0 commit comments

Comments
 (0)