1
0
mirror of https://github.com/dockur/windows.git synced 2026-07-27 21:42:36 +07:00

feat: Merge client and server edition selection (#1955)

This commit is contained in:
Kroese
2026-07-25 02:46:26 +02:00
committed by GitHub
parent 4b5eb2c882
commit d1b3364471
2 changed files with 251 additions and 187 deletions
+28 -1
View File
@@ -37,11 +37,38 @@ USERNAME=$(strip "$USERNAME")
DOMAIN_OU=$(strip "$DOMAIN_OU") DOMAIN_OU=$(strip "$DOMAIN_OU")
WORKGROUP=$(strip "$WORKGROUP") WORKGROUP=$(strip "$WORKGROUP")
EDITION_ORDER=(
"-enterprise|enterprise|enterprise enterprise-*"
"-ultimate|ultimate|ultimate ultimate-*"
"|default|@default n pro pro-* professional professional-* business business-*"
"-iot|iot|iot iot-* enterprise-iot enterprise-iot-*"
"-ltsc|ltsc|ltsc ltsc-* enterprise-ltsc enterprise-ltsc-*"
"-education|education|education education-* pro-education pro-education-*"
"-home|home|home home-*"
"-home-premium|home|home-premium home-premium-*"
"-home-basic|home|home-basic home-basic-*"
"-starter|starter|starter starter-*"
)
SERVER_EDITION_ORDER=(
"|default|@default"
"-datacenter|datacenter|datacenter datacenter-*"
"-enterprise|enterprise|enterprise enterprise-*"
"-web|web|web web-*"
"-foundation|foundation|foundation foundation-*"
"-essentials|essentials|essentials essentials-*"
"-standard-core|standard-core|standard-core standard-core-*"
"-datacenter-core|datacenter-core|datacenter-core datacenter-core-*"
"-enterprise-core|enterprise-core|enterprise-core enterprise-core-*"
"-web-core|web-core|web-core web-core-*"
"-hv|hv|hv hv-*"
)
MIRRORS=3 MIRRORS=3
SUGGEST=""
parseVersion() { parseVersion() {
SUGGEST=""
VERSION=$(strip "$VERSION") VERSION=$(strip "$VERSION")
[ -z "$VERSION" ] && VERSION="win11" [ -z "$VERSION" ] && VERSION="win11"
+223 -186
View File
@@ -80,6 +80,7 @@ hasVersion() {
local selected_id="${selected[$i]}" local selected_id="${selected[$i]}"
for actual in "${actuals[@]}"; do for actual in "${actuals[@]}"; do
[[ "${actual,,}" == "${expected_id,,}" ]] || continue [[ "${actual,,}" == "${expected_id,,}" ]] || continue
local file="/run/assets/$selected_id.xml" local file="/run/assets/$selected_id.xml"
@@ -100,9 +101,8 @@ hasVersion() {
# Editions without a dedicated template can use the generic template. # Editions without a dedicated template can use the generic template.
case "${selected_id,,}" in case "${selected_id,,}" in
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | \ "win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | "win20"* )
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \
"win2019"* | "win2022"* | "win2025"* )
file="/run/assets/${selected_id%%-*}.xml" file="/run/assets/${selected_id%%-*}.xml"
if [ -s "$file" ]; then if [ -s "$file" ]; then
@@ -111,6 +111,7 @@ hasVersion() {
fi fi
;; ;;
esac esac
done done
done done
@@ -119,108 +120,79 @@ hasVersion() {
getVersionPriority() { getVersionPriority() {
local id="${1%-eval}" local id="${1,,}"
local base="$2" local base="${2,,}"
local edition="${id#"$base"}" local order_name="EDITION_ORDER"
local edition entry priority patterns pattern
local result="other" prefix score best_score=-1
edition="${edition#-}" id="${id%-eval}"
case "$edition" in case "$base" in
"iot" | "iot-"* | "enterprise-iot" | "enterprise-iot-"* ) "win20"* )
echo "iot" order_name="SERVER_EDITION_ORDER"
;;
"ltsc" | "ltsc-"* | "enterprise-ltsc" | "enterprise-ltsc-"* )
echo "ltsc"
;;
"enterprise" | "enterprise-"* )
echo "enterprise"
;;
"ultimate" | "ultimate-"* )
echo "ultimate"
;;
"education" | "education-"* | "pro-education" | "pro-education-"* )
echo "education"
;;
"home" | "home-"* )
echo "home"
;;
"starter" | "starter-"* )
echo "starter"
;;
"hv" | "hv-"* )
echo "hv"
;;
"" | "n" | "pro" | "pro-"* | "professional" | "professional-"* | \
"business" | "business-"* )
echo "default"
;;
* )
echo "other"
;; ;;
esac esac
local -n order_ref="$order_name"
edition="${id#"$base"}"
edition="${edition#-}"
# Use the most specific matching pattern. This prevents broad patterns
# such as enterprise-* from taking precedence over enterprise-iot-*.
for entry in "${order_ref[@]}"; do
IFS='|' read -r _ priority patterns <<< "$entry"
for pattern in $patterns; do
if [ "$pattern" = "@default" ]; then
[ -z "$edition" ] || continue
score=1
elif [[ "$pattern" == *"*" ]]; then
prefix="${pattern%\*}"
[[ "$edition" == "$prefix"* ]] || continue
score="${#pattern}"
elif [ "$edition" = "$pattern" ]; then
score="${#pattern}"
else
continue
fi
if (( score > best_score )); then
result="$priority"
best_score="$score"
fi
done
done
echo "$result"
return 0 return 0
} }
detectVersion() { getVersions() {
local xml="$1" local xml="$1"
local suggested="${2:-}" local versions_name="$2"
local result_name="$3" local bases_name="$3"
local index_name="$4" local groups_name="$4"
local -n result="$result_name" local indexes_name="$5"
local -n result_index="$index_name" local -n versions_ref="$versions_name"
local -n bases_ref="$bases_name"
local -a bases=() local -n groups_ref="$groups_name"
local -a groups=() local -n indexes_ref="$indexes_name"
local -a versions=()
local -A image_indexes=()
local -a priorities=(
"enterprise"
"ultimate"
"default"
"iot"
"ltsc"
"education"
"home"
"starter"
"hv"
)
local -a suffixes=(
"-enterprise"
"-ultimate"
""
"-iot"
"-ltsc"
"-education"
"-home"
"-home-premium"
"-home-basic"
"-starter"
"-hv"
)
local -a server_suffixes=(
""
"-datacenter"
"-enterprise"
"-web"
"-foundation"
"-essentials"
"-standard-core"
"-datacenter-core"
"-enterprise-core"
"-web-core"
)
result=""
result_index=""
local image image_index key local image image_index key
local display product platform local display product platform
versions_ref=()
bases_ref=()
groups_ref=()
indexes_ref=()
platform=$(getPlatform "$xml") platform=$(getPlatform "$xml")
while IFS='|' read -r image_index display product image; do while IFS='|' read -r image_index display product image; do
@@ -243,12 +215,12 @@ detectVersion() {
found="Y" found="Y"
key="${candidate_id,,}" key="${candidate_id,,}"
[[ -v "image_indexes[$key]" ]] && continue [[ -v "indexes_ref[$key]" ]] && continue
image_indexes["$key"]="$image_index" indexes_ref["$key"]="$image_index"
versions+=("$candidate_id") versions_ref+=("$candidate_id")
bases+=("$candidate_base") bases_ref+=("$candidate_base")
groups+=("$(getVersionPriority "$candidate_id" "$candidate_base")") groups_ref+=("$(getVersionPriority "$candidate_id" "$candidate_base")")
done done
@@ -291,128 +263,193 @@ detectVersion() {
' <<< "$xml" ' <<< "$xml"
) )
[ "${#versions[@]}" -eq 0 ] && return 0 return 0
}
local base match prefer selectVersion() {
local versions_name="$1"
local indexes_name="$2"
local preferred_name="$3"
local result_name="$4"
local index_name="$5"
local -n version_list="$versions_name"
local -n index_map="$indexes_name"
local -n preference_list="$preferred_name"
local -n selected_version="$result_name"
local -n selected_image_index="$index_name"
local wanted match key
for wanted in "${preference_list[@]}"; do
[ -n "$wanted" ] || continue
if match=$(hasVersion "$wanted" "${version_list[@]}"); then
key="${match,,}"
selected_version="$match"
selected_image_index="${index_map[$key]}"
return 0
fi
done
return 1
}
selectEdition() {
local versions_name="$1"
local bases_name="$2"
local groups_name="$3"
local indexes_name="$4"
local suggested="$5"
local result_name="$6"
local index_name="$7"
local normalize_name="$8"
local order_name="$9"
local -n edition_versions="$versions_name"
local -n edition_bases="$bases_name"
local -n edition_groups="$groups_name"
local -n edition_order="$order_name"
local base edition entry suffix priority i
local -a preferred=()
local -A seen=()
if [ -n "$EDITION" ]; then if [ -n "$EDITION" ]; then
local edition tried="" for base in "${edition_bases[@]}"; do
edition=$("$normalize_name" "$EDITION" "$base")
for base in "${bases[@]}"; do preferred+=("$base${edition:+-$edition}")
case "${base,,}" in
"win20"* )
edition=$(normalizeServerEditionID "$EDITION")
;;
* )
edition=$(normalizeEditionID "$EDITION" "$base")
;;
esac
tried="Y"
prefer="$base"
[ -n "$edition" ] && prefer+="-$edition"
if match=$(hasVersion "$prefer" "${versions[@]}"); then
key="${match,,}"
result="$match"
result_index="${image_indexes[$key]}"
return 0
fi
done done
if [ -n "$tried" ]; then if selectVersion \
warn "edition '$EDITION' is not supported by this image, using automatic selection instead." "$versions_name" \
"$indexes_name" \
preferred \
"$result_name" \
"$index_name"; then
return 0
fi fi
warn "edition '$EDITION' is not supported by this image, using automatic selection instead."
fi fi
# For reused automatic media, prefer the edition selected by parseVersion()
# when that edition is actually present in the image. An explicit EDITION
# remains authoritative because it is handled above.
if [ -n "$suggested" ]; then if [ -n "$suggested" ]; then
if match=$(hasVersion "$suggested" "${versions[@]}"); then preferred=("$suggested")
key="${match,,}"
result="$match"
result_index="${image_indexes[$key]}"
if selectVersion \
"$versions_name" \
"$indexes_name" \
preferred \
"$result_name" \
"$index_name"; then
return 0 return 0
fi fi
fi fi
# Server media defaults to the normal Standard GUI edition. If Standard # First try each canonical edition in its configured order.
# is absent, prefer another known GUI edition before any Core variant. preferred=()
local suffix
for suffix in "${server_suffixes[@]}"; do for entry in "${edition_order[@]}"; do
for base in "${bases[@]}"; do
case "${base,,}" in IFS='|' read -r suffix _ _ <<< "$entry"
"win20"* )
prefer="$base$suffix"
if match=$(hasVersion "$prefer" "${versions[@]}"); then
key="${match,,}"
result="$match"
result_index="${image_indexes[$key]}"
return 0
fi
;;
esac
for base in "${edition_bases[@]}"; do
preferred+=("$base$suffix")
done done
done done
# Prefer the normal edition within each selection family. hasVersion() if selectVersion \
# still allows its Evaluation counterpart when the normal variant is absent. "$versions_name" \
for suffix in "${suffixes[@]}"; do "$indexes_name" \
for base in "${bases[@]}"; do preferred \
"$result_name" \
"$index_name"; then
return 0
fi
prefer="$base$suffix" # Then try noncanonical editions from the same preference groups.
preferred=()
seen=()
if match=$(hasVersion "$prefer" "${versions[@]}"); then for entry in "${edition_order[@]}"; do
key="${match,,}"
result="$match" IFS='|' read -r _ priority _ <<< "$entry"
result_index="${image_indexes[$key]}"
return 0 [[ -v "seen[$priority]" ]] && continue
fi seen["$priority"]="Y"
for ((i=0;i<${#edition_versions[@]};i++)); do
[[ "${edition_groups[$i]}" == "$priority" ]] || continue
preferred+=("${edition_versions[$i]}")
done done
done done
# When the normal edition is absent, select another compatible member of selectVersion \
# that family, such as N, Workstations, or a future dynamic variant. "$versions_name" \
local priority i "$indexes_name" \
preferred \
"$result_name" \
"$index_name"
}
for priority in "${priorities[@]}"; do detectVersion() {
for (( i=0; i<${#versions[@]}; i++ )); do
[[ "${groups[$i]}" == "$priority" ]] || continue local xml="$1"
local suggested="${2:-}"
local result_name="$3"
local index_name="$4"
local -n result_ref="$result_name"
local -n index_ref="$index_name"
local actual="${versions[$i]}" local order_name="EDITION_ORDER"
local normalize_name="normalizeEditionID"
if match=$(hasVersion "$actual" "${versions[@]}"); then local -a bases=()
key="${match,,}" local -a groups=()
result="$match" local -a versions=()
result_index="${image_indexes[$key]}" local -A image_indexes=()
return 0
fi
done
done
# Future or unusual editions that do not belong to a known selection result_ref=""
# family use the first recognized WIM image. index_ref=""
result="${versions[0]}"
key="${result,,}" getVersions \
result_index="${image_indexes[$key]}" "$xml" \
versions \
bases \
groups \
image_indexes
[ "${#versions[@]}" -eq 0 ] && return 0
case "${bases[0],,}" in
"win20"* )
order_name="SERVER_EDITION_ORDER"
normalize_name="normalizeServerEditionID"
;;
esac
selectEdition \
versions \
bases \
groups \
image_indexes \
"$suggested" \
"$result_name" \
"$index_name" \
"$normalize_name" \
"$order_name" && return 0
result_ref="${versions[0]}"
local key="${result_ref,,}"
index_ref="${image_indexes[$key]}"
return 0 return 0
} }
@@ -610,8 +647,8 @@ detectImage() {
local edition local edition
case "${DETECTED,,}" in case "${DETECTED,,}" in
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \ "win20"* )
"win2019"* | "win2022"* | "win2025"* )
edition=$(normalizeServerEditionID "$EDITION") edition=$(normalizeServerEditionID "$EDITION")
if [ -n "$edition" ] && if [ -n "$edition" ] &&