Skip to content

Commit d63af78

Browse files
committed
Fix matching symlink files
This commit fixes that matches of symlink files when the output followLinks option is set to false. Prior this fix symlinks where discarded when glob pattern was matching the name of the link file. However the correct behavior is that the file should be included in the result set as file the represents the symlink. Signed-off-by: Paolo Di Tommaso <[email protected]>
1 parent 4da0442 commit d63af78

File tree

3 files changed

+27
-14
lines changed

3 files changed

+27
-14
lines changed

modules/nextflow/src/test/groovy/nextflow/NextflowTest.groovy

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class NextflowTest extends Specification {
204204
when:
205205
result = Nextflow.files("$folder/**.fa", relative: true, followLinks: false)
206206
then:
207-
result.collect { it.toString() } .sort() == ['dir1/dir2/file4.fa', 'file2.fa']
207+
result.collect { it.toString() } .sort() == ['dir1/dir2/file4.fa', 'file2.fa', 'file_link.fa']
208208

209209
when:
210210
result = Nextflow.files("$folder/**.fa", relative: true, maxDepth: 1)
@@ -227,8 +227,10 @@ class NextflowTest extends Specification {
227227
then:
228228
result.collect { it.toString() } .sort() == ['dir1/dir2/file4.fa',
229229
'dir1/file3.txt',
230+
'dir_link',
230231
'file1.txt',
231-
'file2.fa']
232+
'file2.fa',
233+
'file_link.fa']
232234

233235
when:
234236
result = Nextflow.files("$folder/**", relative: true, type:'dir')
@@ -252,8 +254,10 @@ class NextflowTest extends Specification {
252254
'dir1/dir2',
253255
'dir1/dir2/file4.fa',
254256
'dir1/file3.txt',
257+
'dir_link',
255258
'file1.txt',
256-
'file2.fa']
259+
'file2.fa',
260+
'file_link.fa']
257261

258262
cleanup:
259263
folder?.deleteDir()

modules/nf-commons/src/main/nextflow/file/FileHelper.groovy

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -795,14 +795,15 @@ class FileHelper {
795795
assert filePattern
796796
assert action
797797

798-
final type = options?.type ?: 'any'
799-
final walkOptions = options?.followLinks == false ? EnumSet.noneOf(FileVisitOption.class) : EnumSet.of(FileVisitOption.FOLLOW_LINKS)
800-
final int maxDepth = getMaxDepth(options?.maxDepth, filePattern)
801-
final includeHidden = options?.hidden as Boolean ?: filePattern.startsWith('.')
798+
if( options==null ) options = Map.of()
799+
final type = options.type ?: 'any'
800+
final walkOptions = options.followLinks == false ? EnumSet.noneOf(FileVisitOption.class) : EnumSet.of(FileVisitOption.FOLLOW_LINKS)
801+
final int maxDepth = getMaxDepth(options.maxDepth, filePattern)
802+
final includeHidden = options.hidden as Boolean ?: filePattern.startsWith('.')
802803
final includeDir = type in ['dir','any']
803804
final includeFile = type in ['file','any']
804-
final syntax = options?.syntax ?: 'glob'
805-
final relative = options?.relative == true
805+
final syntax = options.syntax ?: 'glob'
806+
final relative = options.relative == true
806807

807808
final matcher = getPathMatcherFor("$syntax:${filePattern}", folder.fileSystem)
808809
final singleParam = action.getMaximumNumberOfParameters() == 1
@@ -828,7 +829,7 @@ class FileHelper {
828829
final path = folder.relativize(fullPath)
829830
log.trace "visitFiles > file=$path; includeFile=$includeFile; matches=${matcher.matches(path)}; isRegularFile=${attrs.isRegularFile()}"
830831

831-
if (includeFile && matcher.matches(path) && attrs.isRegularFile() && (includeHidden || !isHidden(fullPath))) {
832+
if (includeFile && matcher.matches(path) && (attrs.isRegularFile() || (options.followLinks == false && attrs.isSymbolicLink())) && (includeHidden || !isHidden(fullPath))) {
832833
def result = relative ? path : fullPath
833834
singleParam ? action.call(result) : action.call(result,attrs)
834835
}

modules/nf-commons/src/test/nextflow/file/FileHelperTest.groovy

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,18 +463,26 @@ class FileHelperTest extends Specification {
463463
Files.createSymbolicLink(
464464
folder.resolve('file4.fa'),
465465
folder.resolve('file3.bam'))
466+
and:
467+
folder.resolve('subdir_real').mkdirs()
468+
folder.resolve('subdir_real/file5.fa').text = 'file 5'
469+
and:
470+
Files.createSymbolicLink(
471+
folder.resolve('subdir_link'),
472+
folder.resolve('subdir_real'))
466473

467474
when:
468475
def result = []
469-
FileHelper.visitFiles(folder, '*.fa', relative: true) { result << it.toString() }
476+
FileHelper.visitFiles(folder, '**.fa', relative: true) { result << it.toString() }
470477
then:
471-
result.sort() == ['file2.fa','file4.fa']
478+
result.sort() == ['file2.fa','file4.fa','subdir_link/file5.fa', 'subdir_real/file5.fa']
472479

473480
when:
474481
result = []
475-
FileHelper.visitFiles(folder, '*.fa', relative: true, followLinks: false) { result << it.toString() }
482+
FileHelper.visitFiles(folder, '**.fa', relative: true, followLinks: false) { result << it.toString() }
476483
then:
477-
result.sort() == ['file2.fa']
484+
// note: "file4.fa" is included in the result because it matches the name of the symlink file
485+
result.sort() == ['file2.fa','file4.fa','subdir_real/file5.fa']
478486

479487
cleanup:
480488
folder?.deleteDir()

0 commit comments

Comments
 (0)