Skip to content

Commit b794d9e

Browse files
Strum355claude
andcommitted
refactor: use selectToolBinary for Gradle discovery and remove mocks
Replace resolveBinary with selectToolBinary (via Base_java) in discoverGradleSubprojects, matching the Maven discovery pattern and gaining normalizePath via traverseForWrapper. Remove esmock invokeCommand mocks from happy-path Gradle workspace tests — they now invoke a real gradle binary. Keep esmock only for the error path (gradle not available). Fix settings.gradle.kts fixture to use valid Kotlin DSL syntax. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7e07f94 commit b794d9e

3 files changed

Lines changed: 19 additions & 69 deletions

File tree

src/providers/java_gradle.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import TOML from 'fast-toml'
88

99
import { readLicenseFile } from '../license/license_utils.js'
1010
import Sbom from '../sbom.js'
11-
import { invokeCommand, resolveBinary } from '../tools.js'
11+
import { invokeCommand } from '../tools.js'
1212
import { filterManifestPathsByDiscoveryIgnore, resolveWorkspaceDiscoveryIgnore } from '../workspace.js'
1313

1414
import Base_java, { ecosystem_gradle } from "./base_java.js";
@@ -503,16 +503,21 @@ export async function discoverGradleSubprojects(workspaceRoot, opts = {}) {
503503
return []
504504
}
505505

506-
const localWrapper = 'gradlew' + (process.platform === 'win32' ? '.bat' : '')
507-
const gradleBin = resolveBinary('gradle', localWrapper, root, opts)
508506
const manifestPaths = []
509507

510508
const rootBuildKts = path.join(root, 'build.gradle.kts')
511509
const rootBuild = path.join(root, 'build.gradle')
512-
if (fs.existsSync(rootBuildKts)) {
513-
manifestPaths.push(rootBuildKts)
514-
} else if (fs.existsSync(rootBuild)) {
515-
manifestPaths.push(rootBuild)
510+
const rootManifest = fs.existsSync(rootBuildKts) ? rootBuildKts : fs.existsSync(rootBuild) ? rootBuild : null
511+
if (rootManifest) {
512+
manifestPaths.push(rootManifest)
513+
}
514+
515+
let gradleBin
516+
try {
517+
gradleBin = new Java_gradle().selectToolBinary(rootManifest || rootBuild, opts)
518+
} catch {
519+
const ignorePatterns = [...resolveWorkspaceDiscoveryIgnore(opts), ...DEFAULT_GRADLE_DISCOVERY_IGNORE]
520+
return filterManifestPathsByDiscoveryIgnore(manifestPaths, root, ignorePatterns)
516521
}
517522

518523
const initScriptPath = path.join(os.tmpdir(), `da-list-projects-${crypto.randomUUID()}.gradle`)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
include ':app', ':lib'
1+
include(":app", ":lib")

test/providers/workspace.test.js

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,6 @@ suite('discoverGradleSubprojects', () => {
200200

201201
test('discovers multi-project build', async () => {
202202
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_multi_project')
203-
const initScriptOutput = [
204-
`::DA_PROJECT:::${path.resolve(root)}`,
205-
`::DA_PROJECT:::app::${path.resolve(root, 'app')}`,
206-
`::DA_PROJECT:::lib::${path.resolve(root, 'lib')}`,
207-
].join('\n')
208-
209-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
210-
'../../src/tools.js': {
211-
resolveBinary: () => 'gradle',
212-
invokeCommand: () => Buffer.from(initScriptOutput),
213-
},
214-
})
215203
const result = await discoverGradleSubprojects(root)
216204
expect(result).to.be.an('array')
217205
expect(result).to.have.lengthOf(3)
@@ -222,18 +210,6 @@ suite('discoverGradleSubprojects', () => {
222210

223211
test('discovers nested subprojects', async () => {
224212
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_nested_subprojects')
225-
const initScriptOutput = [
226-
`::DA_PROJECT:::${path.resolve(root)}`,
227-
`::DA_PROJECT:::libs:core::${path.resolve(root, 'libs/core')}`,
228-
`::DA_PROJECT:::libs:util::${path.resolve(root, 'libs/util')}`,
229-
].join('\n')
230-
231-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
232-
'../../src/tools.js': {
233-
resolveBinary: () => 'gradle',
234-
invokeCommand: () => Buffer.from(initScriptOutput),
235-
},
236-
})
237213
const result = await discoverGradleSubprojects(root)
238214
expect(result).to.be.an('array')
239215
expect(result).to.have.lengthOf(3)
@@ -244,18 +220,6 @@ suite('discoverGradleSubprojects', () => {
244220

245221
test('handles mixed Groovy and Kotlin build files', async () => {
246222
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_mixed_variants')
247-
const initScriptOutput = [
248-
`::DA_PROJECT:::${path.resolve(root)}`,
249-
`::DA_PROJECT:::app::${path.resolve(root, 'app')}`,
250-
`::DA_PROJECT:::lib::${path.resolve(root, 'lib')}`,
251-
].join('\n')
252-
253-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
254-
'../../src/tools.js': {
255-
resolveBinary: () => 'gradle',
256-
invokeCommand: () => Buffer.from(initScriptOutput),
257-
},
258-
})
259223
const result = await discoverGradleSubprojects(root)
260224
expect(result).to.be.an('array')
261225
expect(result).to.have.lengthOf(3)
@@ -266,48 +230,29 @@ suite('discoverGradleSubprojects', () => {
266230

267231
test('returns root only when no subprojects', async () => {
268232
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_no_subprojects')
269-
const initScriptOutput = `::DA_PROJECT:::${path.resolve(root)}\n`
270-
271-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
272-
'../../src/tools.js': {
273-
resolveBinary: () => 'gradle',
274-
invokeCommand: () => Buffer.from(initScriptOutput),
275-
},
276-
})
277233
const result = await discoverGradleSubprojects(root)
278234
expect(result).to.be.an('array')
279235
expect(result).to.have.lengthOf(1)
280236
expect(result[0]).to.equal(path.join(root, 'build.gradle'))
281237
})
282238

283-
test('returns root build file when gradle command fails', async () => {
239+
test('returns root build file when gradle is not available', async () => {
284240
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_multi_project')
285-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
241+
const { discoverGradleSubprojects: discoverMocked } = await esmock('../../src/providers/java_gradle.js', {
286242
'../../src/tools.js': {
287-
resolveBinary: () => 'gradle',
288-
invokeCommand: () => { throw new Error('gradle not found') },
243+
getCustomPath: () => '/nonexistent/gradle',
244+
getWrapperPreference: () => false,
245+
invokeCommand: () => { throw Object.assign(new Error('gradle not found'), { code: 'ENOENT' }) },
289246
},
290247
})
291-
const result = await discoverGradleSubprojects(root)
248+
const result = await discoverMocked(root)
292249
expect(result).to.be.an('array')
293250
expect(result).to.have.lengthOf(1)
294251
expect(result[0]).to.equal(path.join(root, 'build.gradle'))
295252
})
296253

297254
test('excludes paths matching workspaceDiscoveryIgnore', async () => {
298255
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_multi_project')
299-
const initScriptOutput = [
300-
`::DA_PROJECT:::${path.resolve(root)}`,
301-
`::DA_PROJECT:::app::${path.resolve(root, 'app')}`,
302-
`::DA_PROJECT:::lib::${path.resolve(root, 'lib')}`,
303-
].join('\n')
304-
305-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
306-
'../../src/tools.js': {
307-
resolveBinary: () => 'gradle',
308-
invokeCommand: () => Buffer.from(initScriptOutput),
309-
},
310-
})
311256
const result = await discoverGradleSubprojects(root, {
312257
workspaceDiscoveryIgnore: ['**/lib/**'],
313258
})

0 commit comments

Comments
 (0)