1+ param (
2+ [ValidateSet (' Simple' , ' Full' )]
3+ [string ]$Mode = ' Full' ,
4+ # 默认取 Pty.Net.csproj 里的 <Version>;也可手动传入(例如 1.0.2-local)
5+ [string ]$Version
6+ )
7+
8+ $ErrorActionPreference = ' Stop' ;
9+
10+ $root = (Resolve-Path - LiteralPath $PSScriptRoot ).Path;
11+ $projDir = Join-Path $root ' NupkgVerify' ;
12+ $releaseDir = Join-Path $root ' Pty.Net\bin\Release' ;
13+ $csproj = Join-Path $root ' Pty.Net\Pty.Net.csproj' ;
14+
15+ function Get-Version {
16+ [xml ]$xml = Get-Content $csproj ;
17+ $pg = @ ($xml.Project.PropertyGroup ) | Where-Object { $_ -and $_.Version } | Select-Object - First 1 ;
18+ if (-not $pg -or -not $pg.Version ) {
19+ throw " <Version> not found in: $csproj " ;
20+ }
21+ return [string ]$pg.Version ;
22+ }
23+
24+ function New-PtyNupkgVerifyProject {
25+ if (-not (Test-Path $projDir )) {
26+ dotnet new console - n NupkgVerify - o $projDir -f net8.0 ;
27+ }
28+ }
29+
30+ function Get-LatestNupkgPath ([string ]$ver = $null ) {
31+ if (-not (Test-Path $releaseDir )) { throw " Release dir not found: $releaseDir " }
32+
33+ $pattern = if ($ver ) { " PTY.$ver *.nupkg" } else { ' PTY.*.nupkg' };
34+ $pkg = Get-ChildItem $releaseDir - Filter $pattern |
35+ Where-Object { $_.Name -notmatch ' \.snupkg$' } |
36+ Sort-Object LastWriteTime - Descending |
37+ Select-Object - First 1 ;
38+
39+ if (-not $pkg ) {
40+ throw " nupkg not found in $releaseDir (pattern: $pattern )" ;
41+ }
42+ return $pkg.FullName ;
43+ }
44+
45+ function Test-ZipHasEntry ([System.IO.Compression.ZipArchive ]$zip , [string ]$fullName ) {
46+ return [bool ]($zip.Entries | Where-Object { $_.FullName -eq $fullName } | Select-Object - First 1 )
47+ }
48+
49+ function Test-ZipHasAnyEntryLike ([System.IO.Compression.ZipArchive ]$zip , [string ]$regex ) {
50+ return [bool ]($zip.Entries | Where-Object { $_.FullName -match $regex } | Select-Object - First 1 )
51+ }
52+
53+ function Test-PtyNupkgLayout ([string ]$pkgPath ) {
54+ if (-not (Test-Path $pkgPath )) { throw " nupkg not found: $pkgPath " }
55+
56+ Add-Type - AssemblyName System.IO.Compression.FileSystem;
57+ $zip = [System.IO.Compression.ZipFile ]::OpenRead($pkgPath );
58+ try {
59+ " --- verifying nupkg ---" ;
60+ " pkg: $pkgPath " ;
61+
62+ # 1) 必须包含 build / buildTransitive targets
63+ if (-not (Test-ZipHasEntry $zip ' build/PTY.targets' )) { throw ' MISSING in nupkg: build/PTY.targets' }
64+ if (-not (Test-ZipHasEntry $zip ' buildTransitive/PTY.targets' )) { throw ' MISSING in nupkg: buildTransitive/PTY.targets' }
65+
66+ # 2) 必须包含 content/deps(targets 会从 content/deps 复制到输出 deps)
67+ if (-not (Test-ZipHasAnyEntryLike $zip ' ^content/deps/' )) { throw ' MISSING in nupkg: content/deps/**' }
68+
69+ # 3) Windows 关键文件(按仓库 deps 结构)
70+ if (-not (Test-ZipHasEntry $zip ' content/deps/conpty/os64/conpty.dll' )) { throw ' MISSING in nupkg: content/deps/conpty/os64/conpty.dll' }
71+ if (-not (Test-ZipHasEntry $zip ' content/deps/conpty/os86/conpty.dll' )) { throw ' MISSING in nupkg: content/deps/conpty/os86/conpty.dll' }
72+ if (-not (Test-ZipHasEntry $zip ' content/deps/winpty/winpty.dll' )) { throw ' MISSING in nupkg: content/deps/winpty/winpty.dll' }
73+ if (-not (Test-ZipHasEntry $zip ' content/deps/winpty/winpty.exe' )) { throw ' MISSING in nupkg: content/deps/winpty/winpty.exe' }
74+ if (-not (Test-ZipHasEntry $zip ' content/deps/winpty/winpty-agent.exe' )) { throw ' MISSING in nupkg: content/deps/winpty/winpty-agent.exe' }
75+ if (-not (Test-ZipHasEntry $zip ' content/deps/winpty/winpty-debugserver.exe' )) { throw ' MISSING in nupkg: content/deps/winpty/winpty-debugserver.exe' }
76+
77+ # 4) 不应该把 native 的 pdb/lib/exp 打进 nupkg(csproj 已 Exclude,这里再验一遍)
78+ $bad = $zip.Entries | Where-Object { $_.FullName -match ' ^content/deps/.+\.(pdb|lib|exp)$' } | Select-Object - ExpandProperty FullName;
79+ if ($bad ) {
80+ " --- unexpected native artifacts in nupkg ---" ;
81+ $bad ;
82+ throw " nupkg contains excluded native artifacts under content/deps (pdb/lib/exp)" ;
83+ }
84+
85+ " OK: nupkg layout verified" ;
86+ }
87+ finally {
88+ $zip.Dispose ();
89+ }
90+ }
91+
92+ function Test-PtyNupkgSimple {
93+ $ver = if ($Version ) { $Version } else { Get-Version };
94+ if (Test-Path $projDir ) { Remove-Item $projDir - Recurse - Force };
95+ New-PtyNupkgVerifyProject ;
96+ Push-Location $projDir ;
97+ dotnet add package PTY - v $ver - s $releaseDir ;
98+ dotnet build;
99+ Pop-Location ;
100+ $out = Join-Path $projDir " bin\Debug\net8.0\deps\conpty\os64\conpty.dll" ;
101+ if (Test-Path $out ) { " OK: copied -> $out " } else { " MISSING: $out " }
102+ }
103+
104+ function Test-PtyNupkgFull {
105+ $ver = if ($Version ) { $Version } else { Get-Version };
106+
107+ # 1) 重新打包(输出在 Pty.Net\bin\Release)
108+ dotnet pack $csproj - c Release;
109+
110+ # 2) 找到刚生成的 nupkg,并做结构校验(build/buildTransitive + content/deps)
111+ $pkg = Get-LatestNupkgPath $ver ;
112+ Test-PtyNupkgLayout $pkg ;
113+
114+ # 3) 清理 NupkgVerify 对 PTY 的缓存安装(只删这个版本,别全局清)
115+ $ptyCacheRoot = Join-Path $env: USERPROFILE ' .nuget\packages\pty' ;
116+ $ptyCacheVer = Join-Path $ptyCacheRoot $ver ;
117+ if (Test-Path $ptyCacheVer ) { Remove-Item $ptyCacheVer - Recurse - Force };
118+
119+ # 4) 让 NupkgVerify 从本地包源安装这个版本并重新编译
120+ New-PtyNupkgVerifyProject ;
121+ Push-Location $projDir ;
122+ dotnet add package PTY - v $ver - s $releaseDir ;
123+ dotnet restore;
124+ dotnet build;
125+ Pop-Location ;
126+
127+ # 5) 验证输出目录是否出现 deps,并检查关键文件
128+ $p = Join-Path $projDir " bin\Debug\net8.0\deps" ;
129+ if (Test-Path $p ) {
130+ " deps exists" ;
131+ $expected = @ (
132+ (Join-Path $p ' conpty\os64\conpty.dll' ),
133+ (Join-Path $p ' conpty\os86\conpty.dll' ),
134+ (Join-Path $p ' winpty\winpty.dll' ),
135+ (Join-Path $p ' winpty\winpty.exe' ),
136+ (Join-Path $p ' winpty\winpty-agent.exe' ),
137+ (Join-Path $p ' winpty\winpty-debugserver.exe' )
138+ );
139+ $missing = $expected | Where-Object { -not (Test-Path $_ ) };
140+ if ($missing ) {
141+ " --- missing deps outputs ---" ;
142+ $missing ;
143+ throw ' deps copied but some expected files are missing' ;
144+ }
145+ " OK: deps files exist in output" ;
146+ }
147+ else {
148+ " deps missing" ;
149+ }
150+ }
151+
152+ if ($Mode -eq ' Simple' ) {
153+ Test-PtyNupkgSimple ;
154+ }
155+ else {
156+ Test-PtyNupkgFull ;
157+ }
158+
159+ # 兼容:保留旧命名习惯(如你有 dot-source 后手动调用)
160+ # Set-Alias -Name Verify-Nupkg -Value Test-PtyNupkgLayout -Scope Script -Force;
161+ # Set-Alias -Name Ensure-VerifyProject -Value New-PtyNupkgVerifyProject -Scope Script -Force;
162+ # Set-Alias -Name Nupkg-Verify-Simple -Value Test-PtyNupkgSimple -Scope Script -Force;
163+ # Set-Alias -Name Nupkg-Verify-Full -Value Test-PtyNupkgFull -Scope Script -Force;
0 commit comments