88  [string []]$PackageNames , 
99  [Parameter (ParameterSetName  =  ' PackageInfo' 
1010  [string ]$PackageInfoDirectory , 
11-   [switch ]$NoVerify  
11+   [switch ]$Verify  
1212)
1313
1414$ErrorActionPreference  =  ' Stop' 
@@ -80,8 +80,8 @@ function Get-CargoPackages() {
8080}
8181
8282function  Get-PackagesToBuild () {
83-   $packages  =  Get-CargoPackages 
84-   $outputPackageNames  =  Get-OutputPackageNames  $packages 
83+   [ array ] $packages  =  Get-CargoPackages 
84+   [ array ] $outputPackageNames  =  Get-OutputPackageNames  $packages 
8585
8686  #  We start with output packages, then recursively add unreleased dependencies to the list of packages that need to be built
8787  [array ]$packagesToBuild  =  $packages  |  Where-Object  { $outputPackageNames.Contains  ($_.name  ) }
@@ -126,26 +126,65 @@ function Get-PackagesToBuild() {
126126  return  $buildOrder 
127127}
128128
129- function  Initialize-VendorDirectory () {
130-   $path  =  " $RepoRoot /target/vendor" 
131-   Invoke-LoggedCommand  " cargo vendor $path " - GroupOutput |  Out-Host 
132-   return  $path 
133- }
129+ #  https://doc.rust-lang.org/cargo/reference/registry-web-api.html#publish
130+ #  https://github.com/rust-lang/cargo/blob/5c87c14f9a162daf10d4133fdaab35c72d67b018/crates/crates-io/lib.rs#L42
131+ function  Get-ApiMetadata ($package ) {
132+   $packagePath  =  Split-Path  - Path $package.manifest_path   - Parent
133+   $readmePath  =  $package.readme   ?  (Join-Path  - Path $packagePath  - ChildPath $package.readme  ) : $null 
134+ 
135+   $jsonBody  =  [ordered ]@ {
136+     ' name' =  $package.name  
137+     ' vers' =  $package.version  
138+     ' deps' =  @ ()
139+     ' features' =  $package.features  
140+     ' authors' =  $package.authors  
141+     ' description' =  $package.description  
142+     ' documentation' =  $package.documentation  
143+     ' homepage' =  $package.homepage  
144+     ' readme' =  if  ($readmePath  -and  (Test-Path  - Path $readmePath )) {
145+       Get-Content  - Path $readmePath  - Raw
146+     }
147+     else  {
148+       $null 
149+     }
150+     ' readme_file' =  $package.readme  
151+     ' keywords' =  $package.keywords  
152+     ' categories' =  $package.categories  
153+     ' license' =  $package.license  
154+     ' license_file' =  $package.license_file  
155+     ' repository' =  $package.repository  
156+     ' links' =  $package.links  
157+     ' rust_version' =  $package.rust_version  
158+   }
134159
135- function  Add-CrateToLocalRegistry ($LocalRegistryPath ,  $Package ) {
136-   $packageName  =  $Package.name  
137-   $packageVersion  =  $Package.version  
160+   foreach  ($dependency  in  $package.dependencies  ) {
161+     $jsonBody.deps   +=  @ {
162+       ' name' =  $dependency.name  
163+       ' version_req' =  $dependency.req  
164+       ' features' =  $dependency.features  
165+       ' optional' =  $dependency.optional  
166+       ' default_features' =  $dependency.default_features  
167+       ' target' =  $dependency.target  
168+       ' kind' =  $dependency.kind  
169+       ' explicit_name_in_toml' =  $dependency.rename  
170+     }
171+   }
138172
139-   #  create an index entry for the package 
140-    $packagePath   =   " $RepoRoot /target/package/ $packageName - $packageVersion " 
173+   return   $jsonBody 
174+ } 
141175
142-   Write-Host  " Copying package '$packageName ' to vendor directory '$LocalRegistryPath '" 
143-   Copy-Item  - Path $packagePath  - Destination $LocalRegistryPath  - Recurse
176+ function  New-ApiPutFile ($crateMetadata ,  $crateFilePath ) {
177+   $metadataBytes  =  [Text.Encoding ]::Utf8.GetBytes($crateMetadata )
178+   $metadataLengthBytes  =  [BitConverter ]::GetBytes([UInt32 ]$metadataBytes.Length  )
179+   $crateBytes  =  [IO.File ]::ReadAllBytes($crateFilePath )
180+   $crateLengthBytes  =  [BitConverter ]::GetBytes([UInt32 ]$crateBytes.Length  )
144181
145-   # write an empty checksum file
146-   ' {"files":{}}' |  Out-File  - FilePath " $LocalRegistryPath /$packageName -$packageVersion /.cargo-checksum.json" - Encoding utf8
182+   $bytes  +=  $metadataLengthBytes  +  $metadataBytes  +  $crateLengthBytes  +  $crateBytes 
183+ 
184+   return  $bytes 
147185}
148186
187+ 
149188function  Create-ApiViewFile ($package ) {
150189  $packageName  =  $package.name  
151190  $command  =  " cargo run --manifest-path $RepoRoot /eng/tools/generate_api_report/Cargo.toml -- --package $packageName " 
@@ -158,61 +197,77 @@ function Create-ApiViewFile($package) {
158197
159198Push-Location  $RepoRoot 
160199try  {
161-   $localRegistryPath  =  Initialize-VendorDirectory 
162- 
163200  [array ]$packages  =  Get-PackagesToBuild 
164201
165-   Write-Host  " Building packages in the following order:" 
202+   $command  =  " cargo +nightly -Zpackage-workspace package --allow-dirty --locked" 
203+ 
204+   Write-Host  " Building packages:" 
166205  foreach  ($package  in  $packages ) {
167206    $packageName  =  $package.name  
168207    $type  =  if  ($package.OutputPackage  ) { " output" else  { " dependency" 
169208    Write-Host  "   $packageName  ($type )" 
209+     $command  +=  "  --package $packageName " 
170210  }
171211
172-   foreach  ($package  in  $packages ) {
173-     Write-Host  " " 
174- 
175-     $packageName  =  $package.name  
176-     $packageVersion  =  $package.version  
177- 
178-     $command  =  " cargo publish --locked --dry-run --package $packageName  --registry crates-io --config `" source.crates-io.replace-with='local'`"  --config `" source.local.directory='$localRegistryPath '`"  --allow-dirty" 
212+   if  (! $Verify ) {
213+     $command  +=  "  --no-verify" 
214+   }
179215
180-     if  ($NoVerify ) {
181-       $command  +=  "  --no-verify" 
182-     }
216+   if  ($env: SYSTEM_DEBUG  -eq  ' true' 
217+     Write-Host  " ##[group] $RepoRoot /Cargo.lock" 
218+     Get-Content  " $RepoRoot /Cargo.lock" 
219+     Write-Host  " ##[endgroup]" 
220+   }
183221
184-      Invoke-LoggedCommand  - Command $command  - GroupOutput
222+   Invoke-LoggedCommand  - Command $command  - GroupOutput
185223
224+   if  ($env: SYSTEM_DEBUG  -eq  ' true' 
225+     Write-Host  " ##[group] $RepoRoot /Cargo.lock" 
226+     Get-Content  " $RepoRoot /Cargo.lock" 
227+     Write-Host  " ##[endgroup]" 
228+   }
186229
187-     #  copy the package to the local registry
188-     Add-CrateToLocalRegistry  ` 
189-       - LocalRegistryPath $localRegistryPath  ` 
190-       - Package $package 
230+   if  ($OutputPath ) {
231+     foreach  ($package  in  $packages  |  Where-Object  { $_.OutputPackage   }) {
232+       $packageName  =  $package.name  
233+       $packageVersion  =  $package.version  
234+       
235+       Write-Host  " `n Processing package '$packageName '" 
191236
192-     if  ($OutputPath  -and  $package.OutputPackage  ) {
193-       $sourcePath  =  " $RepoRoot /target/package/$packageName -$packageVersion " 
237+       $sourcePath  =  " $RepoRoot /target/package/$packageName -$packageVersion .crate" 
194238      $targetPath  =  " $OutputPath /$packageName " 
195239      $targetContentsPath  =  " $targetPath /contents" 
196240      $targetApiReviewFile  =  " $targetPath /$packageName .rust.json" 
241+       $targetCrateFile  =  " $targetPath /$packageName -$packageVersion .crate" 
242+       $targetJsonFile  =  " $targetPath /$packageName -$packageVersion .json" 
243+       $targetBinFile  =  " $targetPath /$packageName .bin" 
197244
198-       if  (Test-Path  - Path $targetContentsPath ) {
199-         Remove-Item  - Path $targetContentsPath  - Recurse - Force
200-       }
201- 
202-       Write-Host  " Copying package '$packageName ' to '$targetContentsPath '" 
245+       Remove-Item  - Path $targetPath  - Recurse - Force - ErrorAction SilentlyContinue
203246      New-Item  - ItemType Directory - Path $targetContentsPath  - Force |  Out-Null 
204-       Copy-Item  - Path $sourcePath /*  - Destination $targetContentsPath  - Recurse - Exclude " Cargo.toml.orig" 
205247
248+       Write-Host  " Copying crate file to '$targetCrateFile '" 
249+       Copy-Item  - Path $sourcePath  - Destination $targetCrateFile  - Force
250+ 
251+       $crateMetadata  =  Get-ApiMetadata  $package  |  ConvertTo-Json  - Depth 10 
252+ 
253+       Write-Host  " Writing crates.io request metadata to '$targetJsonFile '" 
254+       $crateMetadata  |  Out-File  - FilePath " $targetJsonFile " - Encoding utf8
255+ 
256+       $uploadBytes  =  New-ApiPutFile  $crateMetadata  $sourcePath 
257+       Write-Host  " Writing crates.io request bundle to '$targetBinFile '" 
258+       [IO.File ]::WriteAllBytes($targetBinFile ,  $uploadBytes )
259+ 
260+       Write-Host  " Exctracting crate file to '$targetContentsPath '" 
261+       New-Item  - ItemType Directory - Path $targetContentsPath  - Force |  Out-Null 
262+       tar - xf $sourcePath  -- directory $targetContentsPath  -- strip- components= 1  |  Out-Null 
263+       
206264      Write-Host  " Creating API review file" 
207265      $apiReviewFile  =  Create- ApiViewFile $package 
208266
209267      Write-Host  " Copying API review file to '$targetApiReviewFile '" 
210268      Copy-Item  - Path $apiReviewFile  - Destination $targetApiReviewFile  - Force
211269    }
212270  }
213- 
214-   Write-Host  " Removing local registry" 
215-   Remove-Item  - Path $localRegistryPath  - Recurse - Force |  Out-Null 
216271}
217272finally  {
218273  Pop-Location 
0 commit comments