Merge pull request #674 from amartani/master

Fix check-added-large-files --enforce-all to correctly consider all git-lfs files.
diff --git a/pre_commit_hooks/check_added_large_files.py b/pre_commit_hooks/check_added_large_files.py
index 4eaf853..e1beb4e 100644
--- a/pre_commit_hooks/check_added_large_files.py
+++ b/pre_commit_hooks/check_added_large_files.py
@@ -1,24 +1,33 @@
 import argparse
-import json
 import math
 import os
+import subprocess
 from typing import Optional
 from typing import Sequence
 from typing import Set
 
 from pre_commit_hooks.util import added_files
-from pre_commit_hooks.util import CalledProcessError
-from pre_commit_hooks.util import cmd_output
+from pre_commit_hooks.util import zsplit
 
 
-def lfs_files() -> Set[str]:
-    try:
-        # Introduced in git-lfs 2.2.0, first working in 2.2.1
-        lfs_ret = cmd_output('git', 'lfs', 'status', '--json')
-    except CalledProcessError:  # pragma: no cover (with git-lfs)
-        lfs_ret = '{"files":{}}'
+def filter_lfs_files(filenames: Set[str]) -> None:  # pragma: no cover (lfs)
+    """Remove files tracked by git-lfs from the set."""
+    if not filenames:
+        return
 
-    return set(json.loads(lfs_ret)['files'])
+    check_attr = subprocess.run(
+        ('git', 'check-attr', 'filter', '-z', '--stdin'),
+        stdout=subprocess.PIPE,
+        stderr=subprocess.DEVNULL,
+        encoding='utf-8',
+        check=True,
+        input='\0'.join(filenames),
+    )
+    stdout = zsplit(check_attr.stdout)
+    for i in range(0, len(stdout), 3):
+        filename, filter_tag = stdout[i], stdout[i + 2]
+        if filter_tag == 'lfs':
+            filenames.remove(filename)
 
 
 def find_large_added_files(
@@ -30,7 +39,9 @@
     # Find all added files that are also in the list of files pre-commit tells
     # us about
     retv = 0
-    filenames_filtered = set(filenames) - lfs_files()
+    filenames_filtered = set(filenames)
+    filter_lfs_files(filenames_filtered)
+
     if not enforce_all:
         filenames_filtered &= added_files()
 
diff --git a/tests/check_added_large_files_test.py b/tests/check_added_large_files_test.py
index d38c4f6..5d2239b 100644
--- a/tests/check_added_large_files_test.py
+++ b/tests/check_added_large_files_test.py
@@ -121,3 +121,16 @@
         cmd_output('git', 'add', '--', '.')
         # With --enforce-all large files on git lfs should succeed
         assert main(('--enforce-all', '--maxkb', '9', 'f.py')) == 0
+
+
+@xfailif_no_gitlfs  # pragma: no cover
+def test_enforce_allows_gitlfs_after_commit(temp_git_dir, monkeypatch):
+    with temp_git_dir.as_cwd():
+        monkeypatch.setenv('HOME', str(temp_git_dir))
+        cmd_output('git', 'lfs', 'install')
+        temp_git_dir.join('f.py').write('a' * 10000)
+        cmd_output('git', 'lfs', 'track', 'f.py')
+        cmd_output('git', 'add', '--', '.')
+        git_commit('-am', 'foo')
+        # With --enforce-all large files on git lfs should succeed
+        assert main(('--enforce-all', '--maxkb', '9', 'f.py')) == 0