Skip to content

Commit a68a745

Browse files
authored
Merge pull request #22398 from Homebrew/wsl-windows-config-version
config: show Windows build on WSL
2 parents 07cc7c5 + cb25590 commit a68a745

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

Library/Homebrew/extend/os/linux/system_config.rb

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,65 @@ def host_ruby_version
5555
out
5656
end
5757

58+
sig { returns(T.nilable(String)) }
59+
def windows_version
60+
return unless OS.wsl?
61+
62+
cmd = Kernel.which("cmd.exe", ORIGINAL_PATHS) || ::Pathname.new("/mnt/c/Windows/System32/cmd.exe")
63+
return unless cmd.executable?
64+
65+
windows_registry_version(cmd) || Utils.popen_read(cmd, "/d", "/c", "ver", err: :close)
66+
.delete("\r")
67+
.lines
68+
.map(&:strip)
69+
.find { |line| line.start_with?("Microsoft Windows") }
70+
end
71+
72+
sig { params(cmd: ::Pathname).returns(T.nilable(String)) }
73+
def windows_registry_version(cmd)
74+
values = windows_registry_values(cmd)
75+
product_name = values["ProductName"]
76+
build = values["CurrentBuildNumber"]
77+
return if product_name.blank? || build.blank?
78+
79+
product_name = product_name.sub(/\AWindows 10\b/, "Windows 11") if build.to_i >= 22_000
80+
build += ".#{values["UBR"]}" if values["UBR"].present?
81+
82+
version = values["DisplayVersion"] || values["ReleaseId"]
83+
return "#{product_name} [#{build}]" if version.blank?
84+
85+
"#{product_name} (#{version}) [#{build}]"
86+
end
87+
88+
sig { params(cmd: ::Pathname).returns(T::Hash[String, String]) }
89+
def windows_registry_values(cmd)
90+
output = Utils.popen_read(cmd, "/d", "/c", "reg", "query",
91+
"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
92+
err: :close)
93+
94+
output.each_line.with_object({}) do |line, values|
95+
match = line.delete("\r").match(/^\s*(\S+)\s+REG_\S+\s+(.+?)\s*$/)
96+
next if match.nil?
97+
98+
key = match[1]
99+
value = match[2]
100+
next if key.nil? || value.nil?
101+
102+
values[key] = value.start_with?("0x") ? value.to_i(16).to_s : value
103+
end
104+
end
105+
58106
sig { params(out: T.any(File, StringIO, IO)).void }
59107
def dump_verbose_config(out = $stdout)
60108
kernel = Utils.safe_popen_read("uname", "-mors").chomp
61109
super
62110
out.puts "Kernel: #{kernel}"
63111
out.puts "OS: #{OS::Linux.os_version}"
64-
out.puts "WSL: #{OS::Linux.wsl_version}" if OS.wsl?
112+
if OS.wsl?
113+
out.puts "WSL: #{OS::Linux.wsl_version}"
114+
windows = windows_version
115+
out.puts "Windows: #{windows}" if windows
116+
end
65117
out.puts "Host glibc: #{host_glibc_version}"
66118
out.puts "Host libstdc++: #{host_libstdcxx_version}"
67119
out.puts "#{::DevelopmentTools.host_gcc_path}: #{host_gcc_version}"

Library/Homebrew/system_config.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ def kernel
9090
`uname -m`.chomp
9191
end
9292

93+
sig { returns(T.nilable(String)) }
94+
def windows_version; end
95+
9396
sig { returns(String) }
9497
def describe_git
9598
return "N/A" unless Utils::Git.available?

Library/Homebrew/test/cmd/config_spec.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
require "cmd/shared_examples/args_parse"
66

77
RSpec.describe Homebrew::Cmd::Config do
8+
let(:windows_cmd) do
9+
cmd = mktmpdir/"cmd.exe"
10+
cmd.write("")
11+
cmd.chmod(0755)
12+
cmd
13+
end
14+
815
it_behaves_like "parseable arguments"
916

1017
it "prints information about the current Homebrew configuration", :integration_test do
@@ -22,4 +29,40 @@
2229

2330
expect(output.string).to include("HOMEBREW_CASK_OPTS_REQUIRE_SHA: 1")
2431
end
32+
33+
it "reads the Windows version on WSL", :needs_linux do
34+
allow(OS).to receive(:wsl?).and_return(true)
35+
stub_const("ORIGINAL_PATHS", [windows_cmd.dirname])
36+
allow(Utils).to receive(:popen_read)
37+
.with(windows_cmd, "/d", "/c", "reg", "query", "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
38+
err: :close)
39+
.and_return(<<~EOS)
40+
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion
41+
ProductName REG_SZ Windows 10 Pro
42+
DisplayVersion REG_SZ 25H2
43+
CurrentBuildNumber REG_SZ 26200
44+
UBR REG_DWORD 0x2109
45+
EOS
46+
47+
expect(SystemConfig.windows_version).to eq("Windows 11 Pro (25H2) [26200.8457]")
48+
end
49+
50+
it "prints the Windows version in config output on WSL", :needs_linux do
51+
output = StringIO.new
52+
53+
allow(OS).to receive(:wsl?).and_return(true)
54+
allow(OS::Linux).to receive_messages(os_version: "Ubuntu 24.04.3 LTS", wsl_version: Version.new("2"))
55+
allow(SystemConfig).to receive_messages(
56+
homebrew_config: nil,
57+
core_tap_config: nil,
58+
homebrew_env_config: nil,
59+
hardware: nil,
60+
host_software_config: nil,
61+
windows_version: "Windows 11 Pro (25H2) [26200.8457]",
62+
)
63+
64+
SystemConfig.dump_verbose_config(output)
65+
66+
expect(output.string).to include("Windows: Windows 11 Pro (25H2) [26200.8457]\n")
67+
end
2568
end

0 commit comments

Comments
 (0)