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:
+28
-1
@@ -37,11 +37,38 @@ USERNAME=$(strip "$USERNAME")
|
||||
DOMAIN_OU=$(strip "$DOMAIN_OU")
|
||||
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
|
||||
SUGGEST=""
|
||||
|
||||
parseVersion() {
|
||||
|
||||
SUGGEST=""
|
||||
VERSION=$(strip "$VERSION")
|
||||
[ -z "$VERSION" ] && VERSION="win11"
|
||||
|
||||
|
||||
+221
-184
@@ -80,6 +80,7 @@ hasVersion() {
|
||||
local selected_id="${selected[$i]}"
|
||||
|
||||
for actual in "${actuals[@]}"; do
|
||||
|
||||
[[ "${actual,,}" == "${expected_id,,}" ]] || continue
|
||||
|
||||
local file="/run/assets/$selected_id.xml"
|
||||
@@ -100,9 +101,8 @@ hasVersion() {
|
||||
|
||||
# Editions without a dedicated template can use the generic template.
|
||||
case "${selected_id,,}" in
|
||||
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | \
|
||||
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \
|
||||
"win2019"* | "win2022"* | "win2025"* )
|
||||
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | "win20"* )
|
||||
|
||||
file="/run/assets/${selected_id%%-*}.xml"
|
||||
|
||||
if [ -s "$file" ]; then
|
||||
@@ -111,6 +111,7 @@ hasVersion() {
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
done
|
||||
|
||||
@@ -119,108 +120,79 @@ hasVersion() {
|
||||
|
||||
getVersionPriority() {
|
||||
|
||||
local id="${1%-eval}"
|
||||
local base="$2"
|
||||
local edition="${id#"$base"}"
|
||||
local id="${1,,}"
|
||||
local base="${2,,}"
|
||||
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
|
||||
"iot" | "iot-"* | "enterprise-iot" | "enterprise-iot-"* )
|
||||
echo "iot"
|
||||
;;
|
||||
"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"
|
||||
case "$base" in
|
||||
"win20"* )
|
||||
order_name="SERVER_EDITION_ORDER"
|
||||
;;
|
||||
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
|
||||
}
|
||||
|
||||
detectVersion() {
|
||||
getVersions() {
|
||||
|
||||
local xml="$1"
|
||||
local suggested="${2:-}"
|
||||
local result_name="$3"
|
||||
local index_name="$4"
|
||||
local -n result="$result_name"
|
||||
local -n result_index="$index_name"
|
||||
|
||||
local -a bases=()
|
||||
local -a groups=()
|
||||
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 versions_name="$2"
|
||||
local bases_name="$3"
|
||||
local groups_name="$4"
|
||||
local indexes_name="$5"
|
||||
local -n versions_ref="$versions_name"
|
||||
local -n bases_ref="$bases_name"
|
||||
local -n groups_ref="$groups_name"
|
||||
local -n indexes_ref="$indexes_name"
|
||||
|
||||
local image image_index key
|
||||
local display product platform
|
||||
|
||||
versions_ref=()
|
||||
bases_ref=()
|
||||
groups_ref=()
|
||||
indexes_ref=()
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
|
||||
while IFS='|' read -r image_index display product image; do
|
||||
@@ -243,12 +215,12 @@ detectVersion() {
|
||||
|
||||
found="Y"
|
||||
key="${candidate_id,,}"
|
||||
[[ -v "image_indexes[$key]" ]] && continue
|
||||
[[ -v "indexes_ref[$key]" ]] && continue
|
||||
|
||||
image_indexes["$key"]="$image_index"
|
||||
versions+=("$candidate_id")
|
||||
bases+=("$candidate_base")
|
||||
groups+=("$(getVersionPriority "$candidate_id" "$candidate_base")")
|
||||
indexes_ref["$key"]="$image_index"
|
||||
versions_ref+=("$candidate_id")
|
||||
bases_ref+=("$candidate_base")
|
||||
groups_ref+=("$(getVersionPriority "$candidate_id" "$candidate_base")")
|
||||
|
||||
done
|
||||
|
||||
@@ -291,128 +263,193 @@ detectVersion() {
|
||||
' <<< "$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
|
||||
|
||||
local edition tried=""
|
||||
|
||||
for base in "${bases[@]}"; do
|
||||
|
||||
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
|
||||
|
||||
for base in "${edition_bases[@]}"; do
|
||||
edition=$("$normalize_name" "$EDITION" "$base")
|
||||
preferred+=("$base${edition:+-$edition}")
|
||||
done
|
||||
|
||||
if [ -n "$tried" ]; then
|
||||
warn "edition '$EDITION' is not supported by this image, using automatic selection instead."
|
||||
if selectVersion \
|
||||
"$versions_name" \
|
||||
"$indexes_name" \
|
||||
preferred \
|
||||
"$result_name" \
|
||||
"$index_name"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "edition '$EDITION' is not supported by this image, using automatic selection instead."
|
||||
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 match=$(hasVersion "$suggested" "${versions[@]}"); then
|
||||
key="${match,,}"
|
||||
result="$match"
|
||||
result_index="${image_indexes[$key]}"
|
||||
preferred=("$suggested")
|
||||
|
||||
if selectVersion \
|
||||
"$versions_name" \
|
||||
"$indexes_name" \
|
||||
preferred \
|
||||
"$result_name" \
|
||||
"$index_name"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# Server media defaults to the normal Standard GUI edition. If Standard
|
||||
# is absent, prefer another known GUI edition before any Core variant.
|
||||
# First try each canonical edition in its configured order.
|
||||
preferred=()
|
||||
|
||||
local suffix
|
||||
for entry in "${edition_order[@]}"; do
|
||||
|
||||
for suffix in "${server_suffixes[@]}"; do
|
||||
for base in "${bases[@]}"; do
|
||||
|
||||
case "${base,,}" in
|
||||
"win20"* )
|
||||
|
||||
prefer="$base$suffix"
|
||||
|
||||
if match=$(hasVersion "$prefer" "${versions[@]}"); then
|
||||
key="${match,,}"
|
||||
result="$match"
|
||||
result_index="${image_indexes[$key]}"
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
IFS='|' read -r suffix _ _ <<< "$entry"
|
||||
|
||||
for base in "${edition_bases[@]}"; do
|
||||
preferred+=("$base$suffix")
|
||||
done
|
||||
|
||||
done
|
||||
|
||||
# Prefer the normal edition within each selection family. hasVersion()
|
||||
# still allows its Evaluation counterpart when the normal variant is absent.
|
||||
for suffix in "${suffixes[@]}"; do
|
||||
for base in "${bases[@]}"; do
|
||||
if selectVersion \
|
||||
"$versions_name" \
|
||||
"$indexes_name" \
|
||||
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
|
||||
key="${match,,}"
|
||||
result="$match"
|
||||
result_index="${image_indexes[$key]}"
|
||||
return 0
|
||||
fi
|
||||
for entry in "${edition_order[@]}"; do
|
||||
|
||||
IFS='|' read -r _ priority _ <<< "$entry"
|
||||
|
||||
[[ -v "seen[$priority]" ]] && continue
|
||||
seen["$priority"]="Y"
|
||||
|
||||
for ((i=0;i<${#edition_versions[@]};i++)); do
|
||||
[[ "${edition_groups[$i]}" == "$priority" ]] || continue
|
||||
preferred+=("${edition_versions[$i]}")
|
||||
done
|
||||
|
||||
done
|
||||
|
||||
# When the normal edition is absent, select another compatible member of
|
||||
# that family, such as N, Workstations, or a future dynamic variant.
|
||||
local priority i
|
||||
selectVersion \
|
||||
"$versions_name" \
|
||||
"$indexes_name" \
|
||||
preferred \
|
||||
"$result_name" \
|
||||
"$index_name"
|
||||
}
|
||||
|
||||
for priority in "${priorities[@]}"; do
|
||||
for (( i=0; i<${#versions[@]}; i++ )); do
|
||||
detectVersion() {
|
||||
|
||||
[[ "${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
|
||||
key="${match,,}"
|
||||
result="$match"
|
||||
result_index="${image_indexes[$key]}"
|
||||
return 0
|
||||
fi
|
||||
local -a bases=()
|
||||
local -a groups=()
|
||||
local -a versions=()
|
||||
local -A image_indexes=()
|
||||
|
||||
done
|
||||
done
|
||||
result_ref=""
|
||||
index_ref=""
|
||||
|
||||
# Future or unusual editions that do not belong to a known selection
|
||||
# family use the first recognized WIM image.
|
||||
result="${versions[0]}"
|
||||
key="${result,,}"
|
||||
result_index="${image_indexes[$key]}"
|
||||
getVersions \
|
||||
"$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
|
||||
}
|
||||
@@ -610,8 +647,8 @@ detectImage() {
|
||||
local edition
|
||||
|
||||
case "${DETECTED,,}" in
|
||||
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \
|
||||
"win2019"* | "win2022"* | "win2025"* )
|
||||
"win20"* )
|
||||
|
||||
edition=$(normalizeServerEditionID "$EDITION")
|
||||
|
||||
if [ -n "$edition" ] &&
|
||||
|
||||
Reference in New Issue
Block a user