Repository navigation
fix(manifest): run Gradle and sbt on a JDK they support #1665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v1.x
Are you sure you want to change the base?
Changes from all commits
2e1d6d4
69ddd81
31c5a31
e69b664
8b2e827
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,270 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { existsSync, promises as fs } from 'node:fs' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os from 'node:os' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import path from 'node:path' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import semver from 'semver' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { whichBin } from '@socketsecurity/registry/lib/bin' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { safeReadFile } from '@socketsecurity/registry/lib/fs' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { isBuildToolWrapper, resolveBuildToolBin } from './build-tool.mts' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { BuildTool } from './build-tool.mts' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type JavaInstallation = { home: string; feature: number } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type JavaRange = { min: number; max: number } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type BuildJavaHome = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Undefined when no usable JDK is set in JAVA_HOME or found on PATH. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| current: JavaInstallation | undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| picked: JavaInstallation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| toolVersion: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type JavaSupport = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The first release of the tool that runs on each Java release. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runsOnJavaFrom: ReadonlyArray<[number, string]> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The first release that needs Java 17. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needsJava17From: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const JAVA_SUPPORT: Partial<Record<BuildTool, JavaSupport>> = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // https://docs.gradle.org/current/userguide/compatibility.html | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+32
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Nit: CLAUDE.md asks for
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gradle: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runsOnJavaFrom: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [8, '2.0.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [9, '4.3.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [10, '4.7.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [11, '5.0.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [12, '5.4.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [13, '6.0.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [14, '6.3.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [15, '6.7.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [16, '7.0.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [17, '7.3.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [18, '7.5.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [19, '7.6.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [20, '8.3.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [21, '8.5.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [22, '8.8.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [23, '8.10.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [24, '8.14.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [25, '9.1.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needsJava17From: '9.0.0', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // LTS Java releases only. The sbt version is the project's, which the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Nit: "LTS Java releases only" reads as if every LTS has a row, so a reader will wonder whether 21 was forgotten. It's covered because 21 and 25 share the same first sbt release, which may be worth saying. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // launcher downloads and runs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sbt: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runsOnJavaFrom: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [11, '0.13.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Nit: The table caps 0.13.x at 11, but your own measurements show 0.13.18 starting on 17. Since 1.0 to 1.2 don't, a monotonic table can't express that. It's harmless (at worst an unneeded switch to 11), but the comment could mention it so nobody "fixes" the table later. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [17, '1.3.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [25, '1.9.0'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needsJava17From: '2.0.0', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Nit: the other half of the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function javaRange( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tool: BuildTool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): JavaRange | undefined { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const support = JAVA_SUPPORT[tool] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsed = semver.coerce(version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!support || !parsed) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { needsJava17From, runsOnJavaFrom } = support | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const min = semver.gte(parsed, needsJava17From) ? 17 : 8 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Past the table's newest entry the tool may support newer Java than we know | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // of, so any Java counts as supported there. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (semver.gt(parsed, runsOnJavaFrom[runsOnJavaFrom.length - 1]![1])) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+80
to
+82
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Before merge: This makes every release after the newest table entry unbounded, not just new majors. Gradle 9.1.0 caps at 25, but 9.1.1 or 9.2 runs on anything, and likewise sbt 1.9.0 versus 1.9.1. Once a JDK 26 default arrives, a Gradle 9.2 project won't be moved off it, which is the failure this PR fixes. One option: only a newer major is unbounded, and later releases in the same line keep the newest known limit. The cost is an occasional unnecessary switch to an older installed JDK until the table catches up, which seems the safer direction. The test change is in the thread on
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { min, max: Number.POSITIVE_INFINITY } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const max = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runsOnJavaFrom.findLast(([, since]) => semver.gte(parsed, since))?.[0] ?? 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Nit: CLAUDE.md asks for object notation instead of array destructuring.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { min, max } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // `JAVA_VERSION` in a JDK's `release` file: "1.8.0_462", "17.0.16", "25". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function parseJavaFeatureVersion(release: string): number | undefined { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const match = /^JAVA_VERSION="?(\d+)(?:\.(\d+))?/m.exec(release) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!match) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const first = Number(match[1]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return first === 1 && match[2] ? Number(match[2]) : first | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async function readJavaInstallation( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| home: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<JavaInstallation | undefined> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!existsSync(path.join(home, 'bin', 'java'))) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const release = await safeReadFile(path.join(home, 'release')) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const feature = release ? parseJavaFeatureVersion(release) : undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return feature === undefined ? undefined : { home, feature } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function defaultJavaSearchDirs(): string[] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userHome = os.homedir() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '/usr/lib/jvm', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '/usr/lib64/jvm', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '/usr/java', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '/opt/java', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '/Library/Java/JavaVirtualMachines', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(userHome, 'Library', 'Java', 'JavaVirtualMachines'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(userHome, '.sdkman', 'candidates', 'java'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(userHome, '.gradle', 'jdks'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(userHome, '.jdks'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Installed JDKs: the children of each search dir (macOS bundles keep theirs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // under Contents/Home), and the JAVA_HOME_<release>_<arch> variables GitHub | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // and Azure runners set. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function discoverJavaInstallations( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: NodeJS.ProcessEnv, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| searchDirs: readonly string[] = defaultJavaSearchDirs(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<JavaInstallation[]> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const runnerHomes = Object.entries(env).flatMap(([name, value]) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Nit: same array-destructuring convention.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value && /^JAVA_HOME_\d+_/i.test(name) ? [value] : [], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const searchDirHomes = await Promise.all( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| searchDirs.map(async dir => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let children: string[] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| children = await fs.readdir(dir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return children | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .sort() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .flatMap(child => [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(dir, child), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(dir, child, 'Contents', 'Home'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+144
to
+149
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Before merge: Gradle-provisioned JDKs mostly sit one level deeper than this looks, e.g.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const installations = await Promise.all( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [...runnerHomes, ...searchDirHomes.flat()].map(async candidate => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const installation = await readJavaInstallation(candidate) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return installation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? { ...installation, home: await fs.realpath(candidate) } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const seen = new Set<string>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const found: JavaInstallation[] = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const installation of installations) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (installation && !seen.has(installation.home)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| seen.add(installation.home) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| found.push(installation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return found | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The JDK a build tool would run on: JAVA_HOME, else the `java` on PATH. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function currentJavaInstallation( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: NodeJS.ProcessEnv, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<JavaInstallation | undefined> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const javaHome = env['JAVA_HOME'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (javaHome) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await readJavaInstallation(javaHome) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const java = await whichBin('java', { nothrow: true, path: env['PATH'] }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Before merge:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof java !== 'string') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const home = path.dirname(path.dirname(await fs.realpath(java))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // A JDK 8 `java` on PATH can be the one under <home>/jre/bin. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (await readJavaInstallation(home)) ?? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (await readJavaInstallation(path.dirname(home))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async function readProperty( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<string | undefined> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const text = await safeReadFile(file) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const line of text?.split(/\r?\n/) ?? []) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const match = /^\s*([^#!=:\s]+)\s*[=:]\s*(.*?)\s*$/.exec(line) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (match?.[1] === key) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return match[2] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The version the project pins: the Gradle wrapper's distribution, or sbt's | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // `sbt.version`. Undefined for a Gradle on PATH or a custom bin. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function projectBuildToolVersion( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tool: BuildTool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectDir: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bin?: string | undefined, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<string | undefined> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (tool === 'gradle') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const gradleBin = path.resolve( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectDir, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resolveBuildToolBin('gradle', projectDir, bin), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isBuildToolWrapper('gradle', gradleBin)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = await readProperty( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.dirname(gradleBin), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'gradle', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'wrapper', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'gradle-wrapper.properties', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'distributionUrl', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return url ? /gradle-(\d+(?:\.\d+)*)[^/]*\.zip$/.exec(url)?.[1] : undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (tool === 'sbt') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Optional: For sbt, a custom
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await readProperty( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path.join(projectDir, 'project', 'build.properties'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'sbt.version', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // A JDK to run the project's build tool on, when the current one is outside | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the range the tool's pinned version runs on. Undefined keeps the current JDK. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function selectBuildJavaHome( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tool: BuildTool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectDir: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| opts: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bin?: string | undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: NodeJS.ProcessEnv | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| searchDirs?: readonly string[] | undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<BuildJavaHome | undefined> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const toolVersion = await projectBuildToolVersion(tool, projectDir, opts.bin) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const range = toolVersion ? javaRange(tool, toolVersion) : undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!toolVersion || !range) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fits = ({ feature }: JavaInstallation) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| feature >= range.min && feature <= range.max | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const current = await currentJavaInstallation(opts.env) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (current && fits(current)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Before merge: A current JDK we can't identify is treated as one that doesn't fit, so we switch away from a JDK that probably works, and the log says the tool "does not run on" it. On macOS without |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const installed = await discoverJavaInstallations(opts.env, opts.searchDirs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let picked: JavaInstallation | undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const installation of installed) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fits(installation) && installation.feature > (picked?.feature ?? 0)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| picked = installation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return picked ? { current, picked, toolVersion } : undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[agent] Nit:
currentandtoolVersionare only used for the log message inwithBuildJavaHome. Returning just the picked installation, with the message built here, would drop this comment, the nested ternary in the log, and a test that pins the log's inputs as API.