Repository: codespell-project/codespell

Issue:
Hidden directories
Currently this generates some warnings

codespell --check-filenames --skip ./codespell_lib/data,./example/code.c,test_basic.py,*.pyc
##[warning]WARNING: Binary file: ./.git/index 

Which implies we're not ignoring hidden directories.

I don't know if we should or not? Should this follow --check-hidden so hidden files and directories are treated the same?


Discussion:
See also some discussion in #1550:
> Yes probably, though maybe we should make it that you can do `--check-hidden files` or `--check-hidden directories` to do one or the other, and `--check-hidden` does both, and omitting `--check-hidden` ignores both. That way if someone wants to get the old behavior back they would do `--check-hidden directories`.

_Originally posted by @larsoner in https://github.com/codespell-project/codespell/pull/1550#issuecomment-641645556_

> Related discussion in #783.

_Originally posted by @waldyrious in https://github.com/codespell-project/codespell/pull/1550#issuecomment-641924220_

Resolving patch:
diff --git a/codespell_lib/_codespell.py b/codespell_lib/_codespell.py
--- a/codespell_lib/_codespell.py
+++ b/codespell_lib/_codespell.py
@@ -304,8 +304,8 @@ def parse_options(args):
 
     parser.add_argument('-H', '--check-hidden',
                         action='store_true', default=False,
-                        help='check hidden files (those starting with ".") as '
-                             'well')
+                        help='Check hidden files and directories (those '
+                             'starting with ".") as well.')
     parser.add_argument('-A', '--after-context', type=int, metavar='LINES',
                         help='print LINES of trailing context')
     parser.add_argument('-B', '--before-context', type=int, metavar='LINES',
@@ -715,6 +715,8 @@ def main(*args):
                 if glob_match.match(root):  # skip (absolute) directories
                     del dirs[:]
                     continue
+                if is_hidden(root, options.check_hidden):  # dir itself hidden
+                    continue
                 for file_ in files:
                     # ignore hidden files in directories
                     if is_hidden(file_, options.check_hidden):


Test patch:
diff --git a/codespell_lib/tests/test_basic.py b/codespell_lib/tests/test_basic.py
--- a/codespell_lib/tests/test_basic.py
+++ b/codespell_lib/tests/test_basic.py
@@ -5,6 +5,7 @@
 import contextlib
 import os
 import os.path as op
+from shutil import copyfile
 import subprocess
 import sys
 
@@ -321,6 +322,16 @@ def test_check_hidden(tmpdir):
     assert cs.main('--check-hidden', '--check-filenames',
                    op.join(d, '.abandonned.txt')) == 2
     assert cs.main('--check-hidden', '--check-filenames', d) == 2
+    # hidden directory
+    assert cs.main(d) == 0
+    assert cs.main('--check-hidden', d) == 1
+    assert cs.main('--check-hidden', '--check-filenames', d) == 2
+    os.mkdir(op.join(d, '.abandonned'))
+    copyfile(op.join(d, '.abandonned.txt'),
+             op.join(d, '.abandonned', 'abandonned.txt'))
+    assert cs.main(d) == 0
+    assert cs.main('--check-hidden', d) == 2
+    assert cs.main('--check-hidden', '--check-filenames', d) == 5
 
 
 def test_case_handling(tmpdir, capsys):