Skip to content
  • Elijah Newren's avatar
    check-ignore: fix documentation and implementation to match · 7ec8125f
    Elijah Newren authored and Junio C Hamano's avatar Junio C Hamano committed
    
    
    check-ignore has two different modes, and neither of these modes has an
    implementation that matches the documentation.  These modes differ in
    whether they just print paths or whether they also print the final
    pattern matched by the path.  The fix is different for both modes, so
    I'll discuss both separately.
    
    === First (default) mode ===
    
    The first mode is documented as:
    
        For each pathname given via the command-line or from a file via
        --stdin, check whether the file is excluded by .gitignore (or other
        input files to the exclude mechanism) and output the path if it is
        excluded.
    
    However, it fails to do this because it did not account for negated
    patterns.  Commands other than check-ignore verify exclusion rules via
    calling
    
       ... -> treat_one_path() -> is_excluded() -> last_matching_pattern()
    
    while check-ignore has a call path of the form:
    
       ... -> check_ignore()                    -> last_matching_pattern()
    
    The fact that the latter does not include the call to is_excluded()
    means that it is susceptible to to messing up negated patterns (since
    that is the only significant thing is_excluded() adds over
    last_matching_pattern()).  Unfortunately, we can't make it just call
    is_excluded(), because the same codepath is used by the verbose mode
    which needs to know the matched pattern in question.  This brings us
    to...
    
    === Second (verbose) mode ===
    
    The second mode, known as verbose mode, references the first in the
    documentation and says:
    
        Also output details about the matching pattern (if any) for each
        given pathname. For precedence rules within and between exclude
        sources, see gitignore(5).
    
    The "Also" means it will print patterns that match the exclude rules as
    noted for the first mode, and also print which pattern matches.  Unless
    more information is printed than just pathname and pattern (which is not
    done), this definition is somewhat ill-defined and perhaps even
    self-contradictory for negated patterns: A path which matches a negated
    exclude pattern is NOT excluded and thus shouldn't be printed by the
    former logic, while it certainly does match one of the explicit patterns
    and thus should be printed by the latter logic.
    
    === Resolution ==
    
    Since the second mode exists to find out which pattern matches given
    paths, and showing the user a pattern that begins with a '!' is
    sufficient for them to figure out whether the pattern is excluded, the
    existing behavior is desirable -- we just need to update the
    documentation to match the implementation (i.e. it is about printing
    which pattern is matched by paths, not about showing which paths are
    excluded).
    
    For the first or default mode, users just want to know whether a pattern
    is excluded.  As such, the existing documentation is desirable; change
    the implementation to match the documented behavior.
    
    Finally, also adjust a few tests in t0008 that were caught up by this
    discrepancy in how negated paths were handled.
    
    Signed-off-by: default avatarElijah Newren <newren@gmail.com>
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    7ec8125f