isaacs / node-glob

glob functionality for node.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`follow: true` doesn't follow more that 1 symbolic link

pamelalozano16 opened this issue ยท comments

"By default, a ** in a pattern will follow 1 symbolic link if it is not the first item in the pattern, or none if it is the first item in the pattern, following the same behavior as Bash.". However, some dependent modules contain multiple nested symbolic links, and the option follow: true only operates for a single level of symlinks.

dir_foo

foo.txt

dir_bar

foo

dir_baz

bar

In this case
glob.sync('dir_baz/**', {follow:true, nodir:true}) returns foo instead of foo.txt.

@isaacs any thoughts on this? ๐Ÿค”

Seems to be working as intended to me, no?

$ tree
./
โ”œโ”€โ”€ dir_bar/
โ”‚   โ””โ”€โ”€ foo -> ../dir_foo/
โ”œโ”€โ”€ dir_baz/
โ”‚   โ””โ”€โ”€ bar -> ../dir_bar/
โ””โ”€โ”€ dir_foo/
    โ””โ”€โ”€ foo.txt

6 directories, 1 file

$ node
Welcome to Node.js v20.11.0.
Type ".help" for more information.
> require('../').globSync('dir_baz/**', {follow:true})
[
  'dir_baz',
  'dir_baz/bar',
  'dir_baz/bar/foo',
  'dir_baz/bar/foo/foo.txt'
]
> require('../').glob('dir_baz/**', {follow:true}).then(console.log)
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 143,
  [Symbol(trigger_async_id_symbol)]: 132
}
> [
  'dir_baz',
  'dir_baz/bar',
  'dir_baz/bar/foo',
  'dir_baz/bar/foo/foo.txt'
]
> require('../').glob('dir_baz/**', {follow:true, nodir:true}).then(console.log)
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 257,
  [Symbol(trigger_async_id_symbol)]: 246
}
> [ 'dir_baz/bar', 'dir_baz/bar/foo', 'dir_baz/bar/foo/foo.txt' ]

> require('../').globSync('dir_baz/**', {follow:true, nodir: true})
[ 'dir_baz/bar', 'dir_baz/bar/foo', 'dir_baz/bar/foo/foo.txt' ]

In the given example, shouldn't > require('../').globSync('dir_baz/**', {follow:true, nodir: true}) return
[ 'dir_baz/bar/foo/foo.txt' ] only and not [ 'dir_baz/bar', 'dir_baz/bar/foo', 'dir_baz/bar/foo/foo.txt' ]?

I see that if (ifDir && this.opts.nodir) return undefined uses .isDirectory() function from path_scurry, checks if the current .path, is a directory. However, when .path is a symlink that points to a directory it is not skipped.
The path is still added to this.matches, since ifDir equals false.

@pamelalozano16 Yeah, this is interesting. It's not actually a directory, so maybe it should be included. But you've set follow: true, so maybe we should be testing the target rather than the entry itself. I'm somewhat torn.

@frontzhm ่ฏทๅœจๆญคๅค„็š„่ฏ„่ฎบไธญไฝฟ็”จ่‹ฑ่ฏญใ€‚

+1 for treating symlinks to directories as directories with follow: true. I think the expectation when that option is passed is that symlinks become fully transparent representations of whatever they link to as much as possible, and doing otherwise is likely to break users who aren't thinking carefully about edge cases. This also matches the behavior of earlier versions of glob, and so is less likely to cause breakages for users upgrading.

@nex3 Yeah, I've noodled on it more since posting that comment earlier today, and I think you're right. follow:true should be "symlinks are treated as their targets in every way", not "follow symlinks, but still treat them differently than directories".

Will publish once CI says it's ok