Log each command in build-windows-install-disk.sh; build the image in place
Print the command line before every external command (hdiutil, udisksctl, wimlib-imagex, sgdisk, mkfs.fat, mmd, mcopy and so on) so the log shows which command is running. Write the image straight to the output path instead of moving it from the work directory, and remove a partial output if the run fails or is cancelled. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
21604f511f
commit
5468fdc033
1 file changed
+37
-14
@@ -46,8 +46,8 @@ die() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# The build has five steps; step prints a numbered heading for each of them.
|
||||
total_steps=5
|
||||
# The build has four steps; step prints a numbered heading for each of them.
|
||||
total_steps=4
|
||||
step_number=0
|
||||
step() {
|
||||
step_number=$((step_number + 1))
|
||||
@@ -60,6 +60,18 @@ note() {
|
||||
printf ' %s\n' "$*" >&2
|
||||
}
|
||||
|
||||
# show logs a command line before it runs; run logs it and then runs it. Use show
|
||||
# alone where the output of the command is captured.
|
||||
show() {
|
||||
local line
|
||||
printf -v line '%q ' "$@"
|
||||
note "\$ ${line% }"
|
||||
}
|
||||
run() {
|
||||
show "$@"
|
||||
"$@"
|
||||
}
|
||||
|
||||
os="$(uname -s)"
|
||||
case "$os" in
|
||||
Darwin|Linux) ;;
|
||||
@@ -105,7 +117,11 @@ mkdir "$mount_dir"
|
||||
note "work directory: $work_dir"
|
||||
mount_method=""
|
||||
loop_device=""
|
||||
# Set while the output image is being written, so that a failed or cancelled
|
||||
# run does not leave a half-built image behind.
|
||||
partial_output=""
|
||||
cleanup() {
|
||||
[[ -z "$partial_output" ]] || rm -f "$partial_output"
|
||||
case "$mount_method" in
|
||||
hdiutil) hdiutil detach -quiet "$mount_dir" >/dev/null 2>&1 || true ;;
|
||||
udisks)
|
||||
@@ -127,6 +143,7 @@ mount_with_udisks() {
|
||||
return 1
|
||||
fi
|
||||
local setup
|
||||
show udisksctl loop-setup -r -f "$iso"
|
||||
if ! setup="$(udisksctl loop-setup -r -f "$iso" 2>&1)"; then
|
||||
note "udisksctl loop-setup failed: $setup"
|
||||
return 1
|
||||
@@ -142,8 +159,10 @@ mount_with_udisks() {
|
||||
# A desktop session may have mounted the loop device already, which makes
|
||||
# udisksctl mount fail with AlreadyMounted; use that mount point then.
|
||||
local mounted point
|
||||
show lsblk -no MOUNTPOINT "$loop_device"
|
||||
point="$(lsblk -no MOUNTPOINT "$loop_device" 2>/dev/null | head -n 1)"
|
||||
if [[ -z "$point" ]]; then
|
||||
show udisksctl mount -b "$loop_device" -t udf -o ro
|
||||
if mounted="$(udisksctl mount -b "$loop_device" -t udf -o ro 2>&1)"; then
|
||||
# Some udisks versions end the message with a period, others do not.
|
||||
point="$(sed -n 's/^Mounted .* at \(.*\)$/\1/p' <<<"$mounted")"
|
||||
@@ -157,7 +176,7 @@ mount_with_udisks() {
|
||||
fi
|
||||
if [[ ! -d "$point" ]]; then
|
||||
note "no usable mount point for $loop_device (parsed mount point: '${point}')"
|
||||
udisksctl loop-delete -b "$loop_device" >/dev/null 2>&1 || true
|
||||
run udisksctl loop-delete -b "$loop_device" >/dev/null 2>&1 || true
|
||||
mount_method=""
|
||||
return 1
|
||||
fi
|
||||
@@ -169,7 +188,7 @@ step "Reading the ISO $iso (it is UDF, so it has to be mounted)"
|
||||
note "ISO size: $(stat -L "${size_args[@]}" "$iso") bytes"
|
||||
if [[ "$os" == Darwin ]]; then
|
||||
note "mounting with hdiutil at $mount_dir"
|
||||
hdiutil attach -readonly -nobrowse -mountpoint "$mount_dir" "$iso" >/dev/null
|
||||
run hdiutil attach -readonly -nobrowse -mountpoint "$mount_dir" "$iso" >/dev/null
|
||||
mount_method=hdiutil
|
||||
else
|
||||
note "mounting with udisksctl"
|
||||
@@ -187,7 +206,7 @@ note "install.wim: $(stat "${size_args[@]}" "$install_wim") bytes"
|
||||
step "Splitting install.wim into install.swm parts (FAT32 files must stay below 4 GiB)"
|
||||
split_dir="$work_dir/split"
|
||||
mkdir "$split_dir"
|
||||
wimlib-imagex split "$install_wim" "$split_dir/install.swm" 3800 >/dev/null
|
||||
run wimlib-imagex split "$install_wim" "$split_dir/install.swm" 3800 >/dev/null
|
||||
for part in "$split_dir"/install*.swm; do
|
||||
note "$(basename "$part"): $(stat "${size_args[@]}" "$part") bytes"
|
||||
done
|
||||
@@ -204,12 +223,17 @@ image_mib=$(( (content_bytes + content_bytes / 20) / mib + 64 ))
|
||||
step "Creating a $image_mib MiB image with a GPT and one FAT32 partition"
|
||||
note "content to copy: $content_bytes bytes (without install.wim)"
|
||||
|
||||
image="$work_dir/disk.img"
|
||||
truncate -s "${image_mib}m" "$image"
|
||||
sgdisk -o -n 1:2048:0 -t 1:0700 -c 1:WINPE "$image" >/dev/null
|
||||
image="$output"
|
||||
run mkdir -p "$(dirname -- "$output")"
|
||||
# --force replaces an existing image; truncate alone would keep its old content.
|
||||
run rm -f "$image"
|
||||
partial_output="$image"
|
||||
run truncate -s "${image_mib}m" "$image"
|
||||
run sgdisk -o -n 1:2048:0 -t 1:0700 -c 1:WINPE "$image" >/dev/null
|
||||
show sgdisk -i 1 "$image"
|
||||
sectors=$(sgdisk -i 1 "$image" | awk '/^Partition size:/ { print $3 }')
|
||||
[[ -n "$sectors" ]] || die "could not read the partition size"
|
||||
mkfs.fat -F 32 -n WINPE --offset 2048 "$image" $((sectors / 2)) >/dev/null
|
||||
run mkfs.fat -F 32 -n WINPE --offset 2048 "$image" $((sectors / 2)) >/dev/null
|
||||
|
||||
# mtools addresses the partition by its byte offset inside the image.
|
||||
mtools_image="$image@@$((2048 * 512))"
|
||||
@@ -222,6 +246,7 @@ copy_dir() { # copy_dir SOURCE_DIR TARGET_DIR_IN_IMAGE
|
||||
files+=("$entry")
|
||||
done < <(find "$source" -maxdepth 1 -type f ! -path "$install_wim" -print0)
|
||||
if ((${#files[@]} > 0)); then
|
||||
note "\$ mcopy -Q -m -i $mtools_image <${#files[@]} files from ${source#"$mount_dir"} > ::$target/"
|
||||
mcopy -Q -m -i "$mtools_image" "${files[@]}" "::$target/"
|
||||
fi
|
||||
}
|
||||
@@ -232,14 +257,12 @@ dir_count=0
|
||||
while IFS= read -r -d '' dir; do
|
||||
relative="${dir#"$mount_dir"/}"
|
||||
dir_count=$((dir_count + 1))
|
||||
mmd -i "$mtools_image" "::$relative"
|
||||
run mmd -i "$mtools_image" "::$relative"
|
||||
copy_dir "$dir" "$relative"
|
||||
done < <(find "$mount_dir" -mindepth 1 -type d -print0 | sort -z)
|
||||
note "copied $dir_count directories"
|
||||
note "copying the install*.swm parts to sources/"
|
||||
mcopy -Q -m -i "$mtools_image" "$split_dir"/install*.swm "::sources/"
|
||||
run mcopy -Q -m -i "$mtools_image" "$split_dir"/install*.swm "::sources/"
|
||||
|
||||
step "Moving the image to $output"
|
||||
mkdir -p "$(dirname -- "$output")"
|
||||
mv -f "$image" "$output"
|
||||
partial_output=""
|
||||
printf 'Built Windows 11 installation disk: %s\n' "$output"
|
||||
Reference in new issue
Block a user