diff --git a/.chronus/changes/fix-java-emitter-build-tar-windows-2026-07-21-13-18-00.md b/.chronus/changes/fix-java-emitter-build-tar-windows-2026-07-21-13-18-00.md new file mode 100644 index 0000000000..b9b5121597 --- /dev/null +++ b/.chronus/changes/fix-java-emitter-build-tar-windows-2026-07-21-13-18-00.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@azure-tools/typespec-java" +--- + +Read pinned `core/` sources with `git archive --format=zip` + `Expand-Archive` instead of `tar`, which failed on Windows. diff --git a/packages/typespec-java/CONTRIBUTING.md b/packages/typespec-java/CONTRIBUTING.md index 0eb1f72a60..0e8f0ec20c 100644 --- a/packages/typespec-java/CONTRIBUTING.md +++ b/packages/typespec-java/CONTRIBUTING.md @@ -21,17 +21,18 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio Only `src/options.ts` (the Azure-specific emitter options) is committed in this package. The rest of the emitter TypeScript (and tests) is copied from `core/packages/http-client-java/emitter/{src,test}` at build time by `Copy-Sources.ps1` (excluding `options.ts`). The Java `emitter.jar` is -built from `core/packages/http-client-java/generator` by `Build-Generator.ps1` and staged into -`generator/http-client-generator/target/`. +built by `Build-Generator.ps1` from a patched copy of `core/packages/http-client-java/generator` +(see below) and staged into `generator/http-client-generator/target/`. ### Azure customization patch -Before building the jar, `Build-Generator.ps1` applies `core.patch` to the `core/` submodule. -This swaps the unbranded customization engine in `http-client-generator-core` for Azure's +`Copy-Sources.ps1` copies the Java generator sources out of the `core/` submodule into this +package's `./generator` folder and applies `core.patch` to that **copy** — never to `core/` itself. +The patch swaps the unbranded customization engine in `http-client-generator-core` for Azure's `com.azure.tools:azure-autorest-customization` (resolved from Maven Central), so the -`customization-class` emitter option runs against the Azure customization base. The patch is applied -transiently at build time (the script runs `git checkout .` in `core/` to apply and again to revert -it), so commit/stage any local `core/` changes before building. When the `core/` submodule is bumped, +`customization-class` emitter option runs against the Azure customization base. `Build-Generator.ps1` +then builds `emitter.jar` from the patched `./generator`. Because the patch is only ever applied to +the copy, the `core/` submodule working tree stays clean. When the `core/` submodule is bumped, refresh `core.patch` if its context no longer applies. ## Build @@ -53,17 +54,19 @@ pwsh ./Build-TypeSpec.ps1 ### Pinning the core commit (`core-commit.json`) -`Copy-Sources.ps1` copies the emitter sources from the `core/` submodule's current checkout. The -optional `core-commit.json` pins a specific upstream `core` commit to copy from instead: +`Copy-Sources.ps1` reads the emitter/generator sources from the `core/` submodule's current checkout. +The optional `core-commit.json` pins a specific upstream `core` commit to read from instead: ```json { "sha": "3cb616e4e8c3d5b6954bac9832b97445450a71af" } ``` The pinned SHA is fetched if needed and used only when it is **newer** than the current checkout (the -submodule never moves backwards). The submodule is checked out transiently for the copy, then always -restored to its original SHA, keeping `pnpm build` and CI git-status checks clean. To advance the pin, -update the `sha`. +submodule never moves backwards). When the pin is newer, those sources are extracted from that commit +into a temporary directory via `git archive` — the `core/` submodule is **never** checked out or +otherwise modified. This keeps `pnpm build` safe to run alongside the parallel monorepo build (which +reads `core/` concurrently) and keeps CI git-status checks clean. To advance the pin, update the +`sha`. ### Troubleshooting diff --git a/packages/typespec-java/CoreCommit.ps1 b/packages/typespec-java/CoreCommit.ps1 index feb88b602f..3cbc8299fb 100644 --- a/packages/typespec-java/CoreCommit.ps1 +++ b/packages/typespec-java/CoreCommit.ps1 @@ -84,22 +84,23 @@ function Get-CoreSourceRoot { Write-Host "Reading core sources from pinned commit $targetSha (was $originSha) without checking it out" $tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("typespec-java-core-" + [System.Guid]::NewGuid().ToString("N")) New-Item -ItemType Directory -Path $tempDir | Out-Null - $tarPath = Join-Path $tempDir "core.tar" + $zipPath = Join-Path $tempDir "core.zip" try { - git -C $CoreRoot archive -o $tarPath "${targetSha}:$script:CoreJavaSubtree" + # Produce a zip (not tar) and expand it with the built-in Expand-Archive: + # this keeps the whole flow inside PowerShell/.NET and avoids depending on an + # external `tar`, whose behavior varies by platform (notably Git for Windows' + # GNU tar treats a drive-letter path like C:\...\core.tar as a remote host). + git -C $CoreRoot archive --format=zip -o $zipPath "${targetSha}:$script:CoreJavaSubtree" if ($LASTEXITCODE -ne 0) { Write-Error "Failed to archive core commit ${targetSha}:$script:CoreJavaSubtree." } - tar -x -f $tarPath -C $tempDir - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to extract core archive $tarPath." - } + Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force } catch { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue throw } - Remove-Item $tarPath -Force + Remove-Item $zipPath -Force return @{ Root = $tempDir; TempDir = $tempDir } }