Skip to content

Commit 6c15bc8

Browse files
committed
modify module list to skip subdirectories of directories that already contains the .module-info. This folders can't be a module
Signed-off-by: jorgee <jorge.ejarque@seqera.io>
1 parent 0a7ef22 commit 6c15bc8

2 files changed

Lines changed: 54 additions & 14 deletions

File tree

modules/nextflow/src/main/groovy/nextflow/module/ModuleStorage.groovy

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
2727
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
2828
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
2929

30+
import java.nio.file.FileVisitResult
3031
import java.nio.file.Files
3132
import java.nio.file.Path
33+
import java.nio.file.SimpleFileVisitor
34+
import java.nio.file.attribute.BasicFileAttributes
3235
import java.util.stream.Stream
3336
import java.util.zip.ZipEntry
3437
import java.util.zip.ZipInputStream
@@ -136,22 +139,28 @@ class ModuleStorage {
136139

137140
List<InstalledModule> modules = []
138141

139-
try( final walkStream = Files.walk(modulesDir) ) {
140-
walkStream
141-
.filter { Path path -> Files.isDirectory(path) }
142-
.filter { Path path -> Files.exists(path.resolve(MODULE_INFO_FILE)) }
143-
.each { Path moduleDir ->
144-
try {
145-
def rel = modulesDir.relativize(moduleDir)
146-
if( rel.nameCount < 2 ) return // Need at least scope/name
147-
def reference = ModuleReference.parse(rel.toString())
148-
def installed = getInstalledModule(reference)
149-
if( installed ) modules.add(installed)
150-
} catch(Exception e){
151-
// Catching exception to go on inspecting other valid folders
152-
log.debug("Not a valid module reference - $e.message")
142+
try {
143+
Files.walkFileTree(modulesDir, new SimpleFileVisitor<Path>() {
144+
@Override
145+
FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
146+
if( dir == modulesDir ) return FileVisitResult.CONTINUE
147+
if( Files.exists(dir.resolve(MODULE_INFO_FILE)) ) {
148+
try {
149+
def rel = modulesDir.relativize(dir)
150+
if( rel.nameCount >= 2 ) {
151+
def reference = ModuleReference.parse(rel.toString())
152+
def installed = getInstalledModule(reference)
153+
if( installed ) modules.add(installed)
154+
}
155+
} catch(Exception e) {
156+
// Catching exception to go on inspecting other valid folders
157+
log.debug("Not a valid module reference - $e.message")
158+
}
159+
return FileVisitResult.SKIP_SUBTREE
153160
}
161+
return FileVisitResult.CONTINUE
154162
}
163+
})
155164
} catch (IOException e) {
156165
log.warn "Failed to scan modules directory ${modulesDir}: ${e.message}"
157166
}

modules/nextflow/src/test/groovy/nextflow/module/ModuleStorageTest.groovy

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,37 @@ class ModuleStorageTest extends Specification {
207207
]
208208
}
209209

210+
def 'should ignore directories without MODULE_INFO_FILE and not descend into module subdirectories'() {
211+
given:
212+
def storage = new ModuleStorage(tempDir)
213+
214+
// A valid module with subdirectories (bin/, src/)
215+
def moduleDir = storage.getModuleDir(new ModuleReference('nf-core', 'fastqc'))
216+
Files.createDirectories(moduleDir)
217+
moduleDir.resolve('main.nf').text = 'process FASTQC { }'
218+
moduleDir.resolve('meta.yml').text = 'name: nf-core/fastqc\nversion: 1.0.0\n'
219+
ModuleChecksum.save(moduleDir, 'checksum')
220+
// Subdirectories inside the module — must NOT be listed as separate modules
221+
def binDir = moduleDir.resolve('bin')
222+
Files.createDirectories(binDir)
223+
binDir.resolve('fastqc.sh').text = '#!/bin/bash'
224+
def srcDir = moduleDir.resolve('src/main')
225+
Files.createDirectories(srcDir)
226+
srcDir.resolve('helper.groovy').text = 'def foo() {}'
227+
228+
// A plain directory tree with no MODULE_INFO_FILE anywhere — must be ignored entirely
229+
def orphanDir = tempDir.resolve('modules/other-org/tool/deep/nested')
230+
Files.createDirectories(orphanDir)
231+
orphanDir.resolve('somefile.txt').text = 'not a module'
232+
233+
when:
234+
def installed = storage.listInstalled()
235+
236+
then:
237+
installed.size() == 1
238+
installed[0].reference.fullName == 'nf-core/fastqc'
239+
}
240+
210241
def 'should return empty list when no modules installed'() {
211242
given:
212243
def storage = new ModuleStorage(tempDir)

0 commit comments

Comments
 (0)