Skip to content

Commit 588feca

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 67927c4 commit 588feca

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
@@ -198,18 +198,6 @@ suite('discoverGradleSubprojects', () => {
198198

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

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

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

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

281-
test('returns root build file when gradle command fails', async () => {
237+
test('returns root build file when gradle is not available', async () => {
282238
const root = path.resolve('test/providers/tst_manifests/gradle/gradle_multi_project')
283-
const { discoverGradleSubprojects } = await esmock('../../src/providers/java_gradle.js', {
239+
const { discoverGradleSubprojects: discoverMocked } = await esmock('../../src/providers/java_gradle.js', {
284240
'../../src/tools.js': {
285-
resolveBinary: () => 'gradle',
286-
invokeCommand: () => { throw new Error('gradle not found') },
241+
getCustomPath: () => '/nonexistent/gradle',
242+
getWrapperPreference: () => false,
243+
invokeCommand: () => { throw Object.assign(new Error('gradle not found'), { code: 'ENOENT' }) },
287244
},
288245
})
289-
const result = await discoverGradleSubprojects(root)
246+
const result = await discoverMocked(root)
290247
expect(result).to.be.an('array')
291248
expect(result).to.have.lengthOf(1)
292249
expect(result[0]).to.equal(path.join(root, 'build.gradle'))
293250
})
294251

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

0 commit comments

Comments
 (0)