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")
|
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
@@ -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" ] &&
|
||||||
|
|||||||
Reference in New Issue
Block a user