-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Add the following function (name not final) that takes a mapping from basedirs to gitignore patterns and produces an object that takes the gitignore patterns for multiple directories into account at once as appropriate:
compile_tree(
patterns: Mapping[
AnyStr | os.PathLike[AnyStr],
Iterable[AnyStr] | Gitignore[AnyStr]
],
ignorecase: bool = False,
) -> GitignoreTree[AnyStr]-
Basedirs must be normalized and relative, possibly with trailing slashes
-
To refer to the root directory, use
os.curdir(or an empty string?) -
Raises an exception if the same basedir is given more than once
-
If there's an entry for a given basedir, and the patterns for a parent directory match that basedir, should the basedir's patterns be honored (as though the basedir were tracked) or not?
-
Possible alternative API: The user constructs an empty
GitignoreTree(with optionalignorecaseoption) and then adds basedir+patterns pairs one at a time (via__setitem__or some other method?)- If the same basedir is given more than once (even in different forms), the patterns for the old entry are replaced (unless you use some
extend_dir_patterns(basedir, patterns)method)
- If the same basedir is given more than once (even in different forms), the patterns for the old entry are replaced (unless you use some
-
Regardless of which API is used,
GitignoreTrees should be mutable, i.e., it should be possible to add moreGitignores to them after construction. This will be useful when progressively walking a directory tree, e.g., withiterpath.
Notes on how Git combines multiple .gitignore files:
- If
/.gitignorecontainsbarorfoo/bar, andfoo/.gitignorecontains!bar,foo/barwill not be ignored. - If
/.gitignorecontains!bar, andfoo/.gitignorecontainsbar,
foo/barwill be ignored. - If
/.gitignorecontains!foo, andfoo/.gitignorecontainsbar,foo/barwill be ignored. - If
/.gitignorecontainsfooandfoo/.gitignorecontains!bar,foo/barwill be ignored.- If
foo/.gitignoreis forcibly added to Git,foo/barwill still be ignored.
- If
- If
/.gitignorecontains bothbar&foo/.gitignoreandfoo/.gitignorecontains!bar,foo/barwill not be ignored, even iffoo/.gitignoreis forcibly added to Git. - If
foo/.gitignorecontainsfoo, thenfoo/barwill not be ignored. - If
foo/bar/.gitignorecontainsfoo, thenfoo/bar/bazwill not be ignored. - If
.gitignorecontains/bar, thenfoo/barwill not be ignored.
Conclusions:
-
Matching a path in a tree is done by concatenating all
.gitignoresfrom the root of the tree up through the directory containing the path (ordered from the root upwards) and using that as the pattern set to test against, except that a pattern fromfoo/.gitignorewill be tested against paths relative tofoo/.- Note that the rule about testing parent directories first still applies, and each parent directory is only tested against
.gitignores up through the parent's parent directory.
- Note that the rule about testing parent directories first still applies, and each parent directory is only tested against
-
Ignoring a
.gitignorebut not its containing directory has no effect on whether anything in the directory is ignored