Execution Flow of should_ignore
This document explains how the .gitignore
rules are processed by the Runex ignore logic code when should_ignore
is called. We’ll walk through an example call to demonstrate the order of function invocations and internal logic.
Example Scenario
Assume we have a project with the following simple .gitignore
rule stored in a file (located at the root):
*.log
And we want to determine if the file src/app.log
should be ignored.
Step-by-Step Execution Flow
1. Instantiating the Scanner and Loading Patterns
-
Create a Scanner Instance:
AGitIgnoreScanner
is instantiated with the project’s root directory.scanner = GitIgnoreScanner(root_dir="path/to/project")
-
Load Patterns:
The scanner calls itsload_patterns()
method to traverse the directory tree and read all.gitignore
files.
For each.gitignore
file:- Each non-empty, non-comment line is extracted.
- For each such line, a
GitIgnorePattern
instance is created:- In
GitIgnorePattern.__init__
, the pattern is processed:- Negation Check: If the pattern starts with
!
, it is marked as negated. - Directory-only Check: If the pattern ends with
/
, it’s flagged as directory-only. - Case Folding: Optionally converts the pattern to lowercase if case-insensitive matching is required.
- Negation Check: If the pattern starts with
- The method then calls
compile_regex()
to compile a regex if the pattern includes a slash.
- In
2. Calling should_ignore
-
Example Call:
Now suppose we want to check ifsrc/app.log
should be ignored. We call:ignore = scanner.should_ignore("src/app.log", is_dir=False)
3. Normalizing the Path
- Path Normalization:
Insideshould_ignore
, the provided path is normalized to use forward slashes.
For instance,"src\app.log"
becomes"src/app.log"
.
4. Iterating Over Collected Patterns
- Looping Through Patterns:
The scanner iterates over eachGitIgnorePattern
in itsself.patterns
list. For each pattern:- Adjusting for Source Directory:
If the pattern was defined in a subdirectory (i.e. itssource_dir
is non-empty), the path is adjusted by removing the directory prefix.
For example, if a pattern was defined insrc/
, the file path might be trimmed accordingly. - Calling
hits()
:
The scanner then calls the pattern’shits(match_path, is_dir)
method to check for a match.
- Adjusting for Source Directory:
5. Inside GitIgnorePattern.hits()
-
Directory-only Check:
If the pattern is marked as directory-only but the current path is not a directory,hits()
immediately returnsFalse
. -
Determine Matching Method:
- Basename-Only Patterns (no
/
in pattern):- The function extracts the basename of the file (
app.log
). - It then calls
wildmatch()
with the raw pattern (*.log
), the basename, and appropriate flags. - If
wildmatch
returnsWM_MATCH
, the function returnsTrue
.
- The function extracts the basename of the file (
- Patterns Containing a Slash:
- The path is normalized by adding a leading slash (e.g.
/src/app.log
). - The compiled regex from
compile_regex()
is used to attempt a full match against this normalized path. - The outcome (match or no match) is returned.
- The path is normalized by adding a leading slash (e.g.
- Basename-Only Patterns (no
6. Handling Negation and Final Decision
- Processing the Result:
Back inshould_ignore
, ifhits()
returns a match, the result is adjusted for negation:- If the pattern was negated (i.e. started with
!
), the rule is inverted.
- If the pattern was negated (i.e. started with
- Aggregating Results:
The scanner processes all matching patterns. If any pattern indicates the file should be ignored,should_ignore
returnsTrue
; otherwise, it returnsFalse
.
7. Returning the Outcome
- Final Result:
Theshould_ignore
method returns a boolean value indicating whether the file (src/app.log
in our example) should be ignored.
Summary of the Function Call Order
- GitIgnoreScanner Initialization & Loading:
GitIgnoreScanner(root_dir)
GitIgnoreScanner.load_patterns()
- Internally creates multiple
GitIgnorePattern
instances viaGitIgnorePattern.__init__()
- Calls
GitIgnorePattern.compile_regex()
for patterns with slashes
- Internally creates multiple
- Checking a Specific Path:
GitIgnoreScanner.should_ignore("src/app.log", is_dir=False)
- Normalizes the path
- Iterates over each pattern:
- Adjusts the path based on
pattern.source_dir
- Calls
GitIgnorePattern.hits(match_path, is_dir)
- If no slash: calls
wildmatch()
on the basename - If slash present: uses compiled regex for matching
- If no slash: calls
- Adjusts the path based on
- Applies negation rules as needed
- Returns the final decision
This structured flow ensures that each pattern is applied in the correct context, ultimately determining whether the file should be ignored. By following the above steps, the code effectively mimics Git’s own behavior for handling .gitignore
files.
This document should serve as a detailed guide to help anyone understand how the ignore logic processes a file path step by step.