public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
From: "'Felix Moessbauer' via isar-users" <isar-users@googlegroups.com>
To: isar-users@googlegroups.com
Cc: jan.kiszka@siemens.com, Felix Moessbauer <felix.moessbauer@siemens.com>
Subject: [PATCH 4/4] rootfs: manually purge locales instead of using localepurge
Date: Tue, 15 Sep 2026 11:32:58 +0200	[thread overview]
Message-ID: <20260915093258.1818604-5-felix.moessbauer@siemens.com> (raw)
In-Reply-To: <20260915093258.1818604-1-felix.moessbauer@siemens.com>

Using localepurge is problematic as this package first needs to be
installed and later removed from the rootfs again. This is time
consuming and leaves traces in the rootfs.

Instead, we use a dpkg config to not extract the files belonging to
locales we don't want to install. This has the additional benefit of
extracting less, making the overall rootfs install faster. As we no
longer install the localepurge package, less needs to be downloaded and
no traces are left in the rootfs.

Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
---
 .../image-locales-extension.bbclass           | 143 ++++++++++--------
 1 file changed, 79 insertions(+), 64 deletions(-)

diff --git a/meta/classes-recipe/image-locales-extension.bbclass b/meta/classes-recipe/image-locales-extension.bbclass
index 66f3ac8c..02e6fb19 100644
--- a/meta/classes-recipe/image-locales-extension.bbclass
+++ b/meta/classes-recipe/image-locales-extension.bbclass
@@ -21,84 +21,108 @@ def get_locale_gen(d, sep='\n'):
                                for i in locale_gen.split('\\n')
                                if i.strip())))
 
-def get_nopurge(d):
+def get_locale_dirs(d):
+    # Directory names below /usr/share/locale that shall be kept, derived from
+    # the language and language_territory parts of LOCALE_GEN.
     locale_gen = d.getVar("LOCALE_GEN") or ""
-    return '\n'.join(sorted(set(i.strip()
-                                for j in locale_gen.split('\\n')
-                                if j.strip()
-                                for i in (j.split()[0].split("_")[0],
-                                          j.split()[0].split(".")[0],
-                                          j.split()[0]))))
-
-ROOTFS_INSTALL_COMMAND_BEFORE_EXPORT += "image_install_localepurge_download"
-image_install_localepurge_download[weight] = "40"
-image_install_localepurge_download[network] = "${TASK_USE_NETWORK_AND_SUDO}"
-image_install_localepurge_download() {
-    run_privileged_heredoc <<'EOF'
-    set -e
-    ${@insert_isar_mounts(d, d.getVar('ROOTFSDIR'), d.getVar('ROOTFS_MOUNTS') if d.getVar('ISAR_CHROOT_MODE') == 'unshare' else '')}
-    chroot ${ROOTFSDIR} \
-        /usr/bin/apt-get ${ROOTFS_APT_ARGS} -o Debug::NoLocking=1 --download-only localepurge
-EOF
-}
+    return sorted(set(i
+                      for j in locale_gen.split('\\n')
+                      if j.strip()
+                      for i in (j.split()[0].split("_")[0],
+                                j.split()[0].split(".")[0])))
+
+def get_locale_path_include(d):
+    lines = []
+    for name in get_locale_dirs(d):
+        lines.append("path-include=/usr/share/locale/%s" % name)
+        lines.append("path-include=/usr/share/locale/%s/*" % name)
+    return "\n".join(lines)
+
+# Configure dpkg to only unpack the requested locales, so unneeded locale files
+# are never installed. This runs before any package is installed into the image.
+# Locale files that the bootstrap already installed are cleaned up here as well.
+ROOTFS_CONFIGURE_COMMAND += "image_configure_locale_filter"
+image_configure_locale_filter[weight] = "5"
+image_configure_locale_filter() {
+    cat<<__EOF__ > ${WORKDIR}/locale.dpkg-filter
+path-exclude=/usr/share/locale/*
+path-include=/usr/share/locale/locale.alias
+${@get_locale_path_include(d)}
+__EOF__
 
-ROOTFS_INSTALL_COMMAND += "image_install_localepurge_install"
-image_install_localepurge_install[weight] = "700"
-image_install_localepurge_install[network] = "${TASK_USE_NETWORK_AND_SUDO}"
-image_install_localepurge_install() {
+    run_privileged_heredoc <<'EOSUDO'
+        set -e
 
-    # Generate locale and localepurge configuration:
-    cat<<__EOF__ > ${WORKDIR}/locale.gen
-${@get_locale_gen(d)}
-__EOF__
+        mkdir -p '${ROOTFSDIR}/etc/dpkg/dpkg.cfg.d'
+        cat '${WORKDIR}/locale.dpkg-filter' \
+            > '${ROOTFSDIR}/etc/dpkg/dpkg.cfg.d/50isar-locales'
+
+        # Drop locale files the bootstrap installed that are not requested.
+        if [ -d '${ROOTFSDIR}/usr/share/locale' ]; then
+            keep=' locale.alias ${@' '.join(get_locale_dirs(d))} '
+            for entry in '${ROOTFSDIR}'/usr/share/locale/*; do
+                [ -e "$entry" ] || continue
+                name=$(basename "$entry")
+                case "$keep" in
+                    *" $name "*) ;;
+                    *) rm -rf "$entry" ;;
+                esac
+            done
+        fi
+EOSUDO
+}
+
+# Preseed the debconf selection and generate the requested locales up front,
+# before any package is installed, so package maintainer scripts find working
+# locales.
+ROOTFS_CONFIGURE_COMMAND += "image_configure_locale_debconf"
+image_configure_locale_debconf[weight] = "5"
+image_configure_locale_debconf() {
     cat<<__EOF__ > ${WORKDIR}/locale.debconf
 locales     locales/locales_to_be_generated    multiselect ${@get_locale_gen(d, ', ')}
 locales     locales/default_environment_locale select      ${LOCALE_DEFAULT}
+__EOF__
+    cat<<__EOF__ > ${WORKDIR}/locale.gen
+${@get_locale_gen(d)}
 __EOF__
     cat<<__EOF__ > ${WORKDIR}/locale.default
 LANG=${LOCALE_DEFAULT}
-__EOF__
-    cat<<__EOF__ > ${WORKDIR}/locale.nopurge
-#USE_DPKG
-MANDELETE
-DONTBOTHERNEWLOCALE
-#SHOWFREEDSPACE
-#QUICKNDIRTYCALC
-#VERBOSE
-${@get_nopurge(d)}
 __EOF__
 
-    # Install configuration into image:
     run_privileged_heredoc <<'EOSUDO'
         set -e
 
         ${@insert_isar_mounts(d, d.getVar('ROOTFSDIR'), '')}
 
-        localepurge_state='i'
-        if chroot '${ROOTFSDIR}' dpkg -s localepurge 2>/dev/null >&2
-        then
-            echo 'localepurge was installed (leaving it installed later)'
-        else
-            localepurge_state='p'
-            echo 'localepurge was not installed (removing it later)'
-            # track additional packages that will be installed, as these packages might be
-            # in the suggested set of other packages and by that need to be explicitly removed
-            localepurge_pkgs=$(chroot '${ROOTFSDIR}' apt-get ${ROOTFS_APT_ARGS} -s localepurge 2>&1 | sed -n 's/^Inst \([^ ]*\) .*/\1/p')
-            chroot '${ROOTFSDIR}' apt-get ${ROOTFS_APT_ARGS} localepurge
-        fi
-
-        cat '${WORKDIR}/locale.gen' >> '${ROOTFSDIR}/etc/locale.gen'
         cat '${WORKDIR}/locale.default' > '${ROOTFSDIR}/etc/default/locale'
-        cat '${WORKDIR}/locale.nopurge' > '${ROOTFSDIR}/etc/locale.nopurge'
         cat '${WORKDIR}/locale.debconf' > '${ROOTFSDIR}/tmp/locale.debconf'
 
-        # Enter image and trigger locales config and localepurge:
+        # Enable the requested locales by uncommenting them in /etc/locale.gen
+        while read -r locale; do
+            [ -n "$locale" ] || continue
+            sed -i "/$locale/s/^# *//" '${ROOTFSDIR}/etc/locale.gen'
+        done < '${WORKDIR}/locale.gen'
+
         chroot '${ROOTFSDIR}' /bin/sh <<'EOSH'
             set -e
 
-            echo 'running locale debconf-set-selections'
             debconf-set-selections /tmp/locale.debconf
-            rm -f '/tmp/locale.debconf'
+            rm -f /tmp/locale.debconf
+EOSH
+EOSUDO
+}
+
+# The systemd locale.conf symlink can only be created once systemd is installed.
+ROOTFS_INSTALL_COMMAND += "image_configure_locales"
+image_configure_locales[weight] = "100"
+image_configure_locales() {
+    run_privileged_heredoc <<'EOSUDO'
+        set -e
+
+        ${@insert_isar_mounts(d, d.getVar('ROOTFSDIR'), '')}
+
+        chroot '${ROOTFSDIR}' /bin/sh <<'EOSH'
+            set -e
 
             SYSTEMD_VERSION=$(dpkg-query \
                 --showformat='${source:Upstream-Version}' \
@@ -112,15 +136,6 @@ __EOF__
 
             echo 'reconfigure locales'
             dpkg-reconfigure -f noninteractive locales
-
-            echo 'running localepurge'
-            localepurge
 EOSH
-
-        if [ "$localepurge_state" = 'p' ]
-        then
-            echo removing localepurge...
-            chroot '${ROOTFSDIR}' apt-get purge --yes $localepurge_pkgs
-        fi
 EOSUDO
 }
-- 
2.55.0

-- 
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/20260915093258.1818604-5-felix.moessbauer%40siemens.com.

      parent reply	other threads:[~2026-09-15  9:33 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-15  9:32 [PATCH 0/4] Rework locale generation 'Felix Moessbauer' via isar-users
2026-09-15  9:32 ` [PATCH 1/4] testsuite: add test for " 'Felix Moessbauer' via isar-users
2026-09-15  9:32 ` [PATCH 2/4] bootstrap: avoid leading space in locale config 'Felix Moessbauer' via isar-users
2026-09-15  9:32 ` [PATCH 3/4] fix(rootfs): only set custom locale in image recipe 'Felix Moessbauer' via isar-users
2026-09-15  9:32 ` 'Felix Moessbauer' via isar-users [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260915093258.1818604-5-felix.moessbauer@siemens.com \
    --to=isar-users@googlegroups.com \
    --cc=felix.moessbauer@siemens.com \
    --cc=jan.kiszka@siemens.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox