Fix core.excludesfile named .gitignore

Ignore rules with slashes in them are matched using `FNM_PATHNAME` and use the path to the `.gitignore` file from the root of the repository along with the path fragment (including slashes) in the ignore file itself.  Unfortunately, the relative path to the `.gitignore` file was being applied to the global `core.excludesfile` if that also happened to be named ".gitignore".

This fixes that with more precise matching and includes test for ignore rules with leading slashes (which were the primary example of this being broken in the real world).

This also backports an improvement to the file context logic from the threadsafe-iterators branch (i.e. PR #2108) so we don't rely on mutating the key of the attribute file name to generate the context path. Instead, the matching rule parser just expects a trailing filename and strips it off when it parses the rule.

This is an alternate fix for Issue #2266 to PR #2267  - sorry @robrix, once I wrote the tests, it was easier just to write the fix for this as well...