Confusing behaviour when trying to ignore direct and indirect child files (involving curly bracketed alternatives)

This is a question regarding ignore pattern rules. I’ve been getting quite confused with the following problem. Let’s say I want to ignore all files called document.txt which are direct and indirect children of a folder called Documents, e.g.

Documents/document.txt
Documents/Photos/document.txt

image

A pattern like Documents/**/document.txt matches both files.

image

image

Now, I’d like to also ignore files called image.jpg, so I add Documents/**/{document.txt,image.jpg} to the patterns.

image

However, this results in ignoring only Documents/Photos/document.txt and not Documents/document.txt. In fact, just doing Documents/**/{document.txt} also results in the same behaviour.

image

Is this normal? If yes, why is it so that Documents/**/document.txt and Documents/**/{document.txt} create different results? For the record, when not using /**/ in the patterns, the problem doesn’t happen, i.e. {document.txt} matches both files.

Lastly, doing something funky like Documents{/**/}{document.txt} also matches both files but I’ve got little idea why :dotted_line_face:.

image

image

That all sounds like a bug, either in our expansion of the patterns or in the pattern matching library itself.

Reported under https://github.com/syncthing/syncthing/issues/8733.

Just one more quirk not mentioned previously. The last pattern of Documents{/**/}{document.txt} matches both files but when replaced with something like Documents{abc,/**/}{document.txt}, it stops matching anything. However, if the order of alternatives is reversed to Documents{/**/,abc}{document.txt}, then it does match both files again.