Skip to content

Commit f7038e2

Browse files
committed
feat: add COMMAND config option allowing override the default one
1 parent 712715d commit f7038e2

8 files changed

Lines changed: 137 additions & 3 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ Edit `/etc/atomic.conf`:
166166
| `MAPPER_NAME` | `root_crypt` | dm-crypt mapper name (fallback if auto-detection fails) |
167167
| `KERNEL_PKG` | `linux` | Kernel package (linux/linux-lts/linux-zen) |
168168
| `KERNEL_PARAMS` | *(security defaults)* | Kernel command line parameters |
169+
| `COMMAND` | *(none)* | Default command in snapshot chroot (overrides built-in `pacman -Syu`) |
169170
| `SBCTL_SIGN` | `0` | Sign UKI files with sbctl for Secure Boot (`0`=off, `1`=on) |
170171
| `UPGRADE_GUARD` | `1` | Upgrade guard: block direct `pacman -Syu` (`0`=off, `1`=on) |
171172
| `HOME_COPY_FILES` | *(empty)* | Files to copy into isolated home subvolumes (see [Home isolation](#home-isolation)) |

‎bin/atomic-upgrade‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ if [[ -n "$CUSTOM_TAG" ]]; then
106106
fi
107107
fi
108108

109-
# Default chroot command
109+
# Default chroot command: use COMMAND from config (or default in common.sh).
110+
# Note: COMMAND uses simple word splitting; args with spaces inside
111+
# are not supported (same limitation as HOME_COPY_FILES).
110112
if [[ ${#CHROOT_CMD[@]} -eq 0 ]]; then
111-
CHROOT_CMD=(/usr/bin/pacman -Syu)
113+
read -ra CHROOT_CMD <<< "$COMMAND"
112114
fi
113115

114116
# Verify required variables are set

‎etc/atomic.conf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
#KERNEL_PKG="linux"
88
#KERNEL_PARAMS="rw slab_nomerge init_on_alloc=1 page_alloc.shuffle=1 pti=on vsyscall=none randomize_kstack_offset=on debugfs=off"
99

10+
# Default command to run in the snapshot chroot (overrides built-in default)
11+
# Command-line -- COMMAND... overrides this setting
12+
# Note: args with spaces inside are not supported (simple word splitting)
13+
#COMMAND="/usr/bin/pacman -Syu"
14+
1015
# Note: inline comments start at ' #' (space + hash).
1116
# Values containing a literal ' #' will be truncated at that point.
1217

‎lib/atomic/common.sh‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ UPGRADE_GUARD=1
2929
HOME_COPY_FILES=""
3030
# Kernel security parameters
3131
KERNEL_PARAMS="rw slab_nomerge init_on_alloc=1 page_alloc.shuffle=1 pti=on vsyscall=none randomize_kstack_offset=on debugfs=off"
32+
# Default chroot command (overridden by config or CLI -- COMMAND...)
33+
COMMAND="/usr/bin/pacman -Syu"
3234

3335
# ── Config loading (safe parser, no arbitrary code execution) ───────
3436

@@ -46,7 +48,7 @@ load_config() {
4648
fi
4749

4850
# Whitelist of allowed config keys
49-
local -a allowed=(BTRFS_MOUNT NEW_ROOT ESP KEEP_GENERATIONS MAPPER_NAME KERNEL_PARAMS KERNEL_PKG SBCTL_SIGN UPGRADE_GUARD HOME_COPY_FILES)
51+
local -a allowed=(BTRFS_MOUNT NEW_ROOT ESP KEEP_GENERATIONS MAPPER_NAME KERNEL_PARAMS KERNEL_PKG COMMAND SBCTL_SIGN UPGRADE_GUARD HOME_COPY_FILES)
5052

5153
while IFS='=' read -r key value; do
5254
# Strip leading/trailing whitespace from key

‎man/atomic.conf.5‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ device arguments.
7171
Default: \f[B]rw slab_nomerge init_on_alloc=1 page_alloc.shuffle=1
7272
pti=on vsyscall=none randomize_kstack_offset=on debugfs=off\f[R].
7373
.TP
74+
\f[B]COMMAND\f[R]
75+
Default command to run in the snapshot chroot, overriding the built\-in
76+
default of \f[B]pacman \-Syu\f[R].
77+
Command\-line \f[B]\-\-\f[R] \f[I]COMMAND...\f[R] takes priority over
78+
this setting.
79+
Note: arguments with spaces inside are not supported due to simple word
80+
splitting.
81+
Default: \f[I](none)\f[R].
82+
.TP
7483
\f[B]SBCTL_SIGN\f[R]
7584
Enable UKI signing with \f[B]sbctl\f[R](8) for Secure Boot.
7685
Set to \f[B]1\f[R] to enable, \f[B]0\f[R] to disable.

‎man/atomic.conf.5.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ rejected entirely.
6666
page_alloc.shuffle=1 pti=on vsyscall=none randomize_kstack_offset=on
6767
debugfs=off**.
6868

69+
**COMMAND**
70+
: Default command to run in the snapshot chroot, overriding the built-in
71+
default of **pacman -Syu**. Command-line **-- COMMAND...** takes priority
72+
over this setting. Note: arguments with spaces inside are not supported
73+
due to simple word splitting. Default: *(none)*.
74+
6975
**SBCTL_SIGN**
7076
: Enable UKI signing with **sbctl**(8) for Secure Boot. Set to **1** to
7177
enable, **0** to disable. When disabled, UKI files are built unsigned.

‎tests/test_config.sh‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,40 @@ assert_eq "HOME_COPY_FILES absent → stays empty" "" "$HOME_COPY_FILES"
276276
# Restore
277277
HOME_COPY_FILES=""
278278

279+
# ── COMMAND config ───────────────────────────────────
279280

281+
section "COMMAND config"
282+
283+
# Test: COMMAND loaded from config
284+
CONFIG_FILE="${TESTDIR}/command.conf"
285+
cat > "$CONFIG_FILE" <<'EOF'
286+
COMMAND=/usr/bin/pacman -Syu
287+
EOF
288+
COMMAND=""
289+
load_config
290+
assert_eq "COMMAND loaded from config" "/usr/bin/pacman -Syu" "$COMMAND"
291+
COMMAND=""
292+
293+
# Test: COMMAND with quotes
294+
CONFIG_FILE="${TESTDIR}/command_quoted.conf"
295+
cat > "$CONFIG_FILE" <<'EOF'
296+
COMMAND="/usr/bin/pacman -S nvidia"
297+
EOF
298+
COMMAND=""
299+
load_config
300+
assert_eq "COMMAND with double quotes" "/usr/bin/pacman -S nvidia" "$COMMAND"
301+
COMMAND=""
302+
303+
# Test: COMMAND absent → stays empty
304+
CONFIG_FILE="${TESTDIR}/command_absent.conf"
305+
cat > "$CONFIG_FILE" <<'EOF'
306+
KEEP_GENERATIONS=3
307+
EOF
308+
COMMAND=""
309+
load_config
310+
assert_eq "COMMAND absent → stays empty" "" "$COMMAND"
311+
312+
#
280313
# ── config key whitespace trimming ─────────────
281314

282315
section "Config key whitespace trimming"

‎tests/test_upgrade.sh‎

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,82 @@ assert_eq "default cmd count" "CHROOT_CMD_COUNT=2" "$(echo "$_out" | grep '^CHRO
196196
assert_eq "default cmd[0]" "CHROOT_CMD_0=/usr/bin/pacman" "$(echo "$_out" | grep '^CHROOT_CMD_0=')"
197197
assert_eq "default cmd[1]" "CHROOT_CMD_1=-Syu" "$(echo "$_out" | grep '^CHROOT_CMD_1=')"
198198

199+
# ── Word splitting limitation: args with spaces ────────────
200+
201+
section "Word splitting limitation (space in args)"
202+
203+
CONFIG_FILE="${TESTDIR}/word_split.conf"
204+
cat > "$CONFIG_FILE" <<'EOF'
205+
COMMAND=/usr/bin/pacman -S nvidia driver
206+
EOF
207+
208+
_TEST_SCRIPT_WS="${TESTDIR}/atomic-upgrade-word-split"
209+
sed \
210+
-e 's|^\(export ATOMIC_UPGRADE=1\)$|\1\nCONFIG_FILE="${CONFIG_FILE:-/etc/atomic.conf}"|' \
211+
-e 's/^\(\[\[ \$EUID -eq 0 \]\]\)/# \1/' \
212+
-e '/^# Verify required variables are set$/i\
213+
if [[ "${ATOMIC_EXIT_AFTER_PARSE:-}" == "1" ]]; then\
214+
echo "PARSE_OK"\
215+
echo "CHROOT_CMD_COUNT=${#CHROOT_CMD[@]}"\
216+
for i in "${!CHROOT_CMD[@]}"; do\
217+
echo "CHROOT_CMD_${i}=${CHROOT_CMD[$i]}"\
218+
done\
219+
exit 0\
220+
fi\
221+
' \
222+
"$SCRIPT" > "$_TEST_SCRIPT_WS"
223+
chmod +x "$_TEST_SCRIPT_WS"
224+
225+
run_cmd env CONFIG_FILE="$CONFIG_FILE" ATOMIC_EXIT_AFTER_PARSE=1 bash "$_TEST_SCRIPT_WS"
226+
assert_eq "word split: PARSE_OK" "0" "$_rc"
227+
assert_eq "word split: count is 4" "CHROOT_CMD_COUNT=4" "$(echo "$_out" | grep '^CHROOT_CMD_COUNT=')"
228+
assert_eq "word split: arg[2]" "CHROOT_CMD_2=nvidia" "$(echo "$_out" | grep '^CHROOT_CMD_2=')"
229+
assert_eq "word split: arg[3]" "CHROOT_CMD_3=driver" "$(echo "$_out" | grep '^CHROOT_CMD_3=')"
230+
231+
rm -f "$_TEST_SCRIPT_WS"
232+
233+
# ── CLI -- COMMAND priority over config COMMAND= ────────────
234+
235+
section "CLI -- COMMAND priority over config COMMAND="
236+
237+
CONFIG_FILE="${TESTDIR}/cli_priority.conf"
238+
cat > "$CONFIG_FILE" <<'EOF'
239+
COMMAND=/usr/bin/pacman -Syu
240+
EOF
241+
242+
_TEST_SCRIPT_CLI="${TESTDIR}/atomic-upgrade-cli-priority"
243+
sed \
244+
-e 's|^\(export ATOMIC_UPGRADE=1\)$|\1\nCONFIG_FILE="${CONFIG_FILE:-/etc/atomic.conf}"|' \
245+
-e 's/^\(\[\[ \$EUID -eq 0 \]\]\)/# \1/' \
246+
-e '/^# Verify required variables are set$/i\
247+
if [[ "${ATOMIC_EXIT_AFTER_PARSE:-}" == "1" ]]; then\
248+
echo "PARSE_OK"\
249+
echo "DRY_RUN=${DRY_RUN}"\
250+
echo "CUSTOM_TAG=${CUSTOM_TAG}"\
251+
echo "NO_GC=${NO_GC}"\
252+
echo "SEPARATE_HOME=${SEPARATE_HOME}"\
253+
echo "COPY_FILES=${COPY_FILES}"\
254+
echo "CHROOT_CMD_COUNT=${#CHROOT_CMD[@]}"\
255+
for i in "${!CHROOT_CMD[@]}"; do\
256+
echo "CHROOT_CMD_${i}=${CHROOT_CMD[$i]}"\
257+
done\
258+
echo "COMMAND_FROM_CONFIG=${COMMAND:-}"\
259+
exit 0\
260+
fi\
261+
' \
262+
"$SCRIPT" > "$_TEST_SCRIPT_CLI"
263+
chmod +x "$_TEST_SCRIPT_CLI"
264+
265+
run_cmd env CONFIG_FILE="$CONFIG_FILE" ATOMIC_EXIT_AFTER_PARSE=1 bash "$_TEST_SCRIPT_CLI" -- /usr/bin/pacman -S nvidia
266+
assert_eq "CLI priority: PARSE_OK" "0" "$_rc"
267+
assert_contains "CLI priority: uses CLI args" "CHROOT_CMD_0=/usr/bin/pacman" "$_out"
268+
assert_contains "CLI priority: CLI arg[1]" "CHROOT_CMD_1=-S" "$_out"
269+
assert_contains "CLI priority: CLI arg[2]" "CHROOT_CMD_2=nvidia" "$_out"
270+
assert_eq "CLI priority: count is 3" "CHROOT_CMD_COUNT=3" "$(echo "$_out" | grep '^CHROOT_CMD_COUNT=')"
271+
assert_contains "CLI priority: COMMAND loaded from config" "COMMAND_FROM_CONFIG=/usr/bin/pacman -Syu" "$_out"
272+
273+
rm -f "$_TEST_SCRIPT_CLI"
274+
199275
# ── GEN_ID format validation ────────────────────────────────
200276

201277
section "GEN_ID format validation"

0 commit comments

Comments
 (0)