mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
Merge pull request #912 from asottile/intent_to_add
Fix staged-files-only for `git add --intent-to-add` files
This commit is contained in:
commit
84c398d6f4
4 changed files with 71 additions and 5 deletions
|
|
@ -97,6 +97,20 @@ def get_staged_files():
|
||||||
)[1])
|
)[1])
|
||||||
|
|
||||||
|
|
||||||
|
def intent_to_add_files():
|
||||||
|
_, stdout_binary, _ = cmd_output('git', 'status', '--porcelain', '-z')
|
||||||
|
parts = list(reversed(zsplit(stdout_binary)))
|
||||||
|
intent_to_add = []
|
||||||
|
while parts:
|
||||||
|
line = parts.pop()
|
||||||
|
status, filename = line[:3], line[3:]
|
||||||
|
if status[0] in {'C', 'R'}: # renames / moves have an additional arg
|
||||||
|
parts.pop()
|
||||||
|
if status[1] == 'A':
|
||||||
|
intent_to_add.append(filename)
|
||||||
|
return intent_to_add
|
||||||
|
|
||||||
|
|
||||||
def get_all_files():
|
def get_all_files():
|
||||||
return zsplit(cmd_output('git', 'ls-files', '-z')[1])
|
return zsplit(cmd_output('git', 'ls-files', '-z')[1])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,11 @@ import logging
|
||||||
import os.path
|
import os.path
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from pre_commit import git
|
||||||
from pre_commit.util import CalledProcessError
|
from pre_commit.util import CalledProcessError
|
||||||
from pre_commit.util import cmd_output
|
from pre_commit.util import cmd_output
|
||||||
from pre_commit.util import mkdirp
|
from pre_commit.util import mkdirp
|
||||||
|
from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('pre_commit')
|
logger = logging.getLogger('pre_commit')
|
||||||
|
|
@ -24,11 +26,22 @@ def _git_apply(patch):
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def staged_files_only(patch_dir):
|
def _intent_to_add_cleared():
|
||||||
"""Clear any unstaged changes from the git working directory inside this
|
intent_to_add = git.intent_to_add_files()
|
||||||
context.
|
if intent_to_add:
|
||||||
"""
|
logger.warning('Unstaged intent-to-add files detected.')
|
||||||
# Determine if there are unstaged files
|
|
||||||
|
xargs(('git', 'rm', '--cached', '--'), intent_to_add)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
xargs(('git', 'add', '--intent-to-add', '--'), intent_to_add)
|
||||||
|
else:
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _unstaged_changes_cleared(patch_dir):
|
||||||
tree = cmd_output('git', 'write-tree')[1].strip()
|
tree = cmd_output('git', 'write-tree')[1].strip()
|
||||||
retcode, diff_stdout_binary, _ = cmd_output(
|
retcode, diff_stdout_binary, _ = cmd_output(
|
||||||
'git', 'diff-index', '--ignore-submodules', '--binary',
|
'git', 'diff-index', '--ignore-submodules', '--binary',
|
||||||
|
|
@ -71,3 +84,12 @@ def staged_files_only(patch_dir):
|
||||||
# There weren't any staged files so we don't need to do anything
|
# There weren't any staged files so we don't need to do anything
|
||||||
# special
|
# special
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def staged_files_only(patch_dir):
|
||||||
|
"""Clear any unstaged changes from the git working directory inside this
|
||||||
|
context.
|
||||||
|
"""
|
||||||
|
with _intent_to_add_cleared(), _unstaged_changes_cleared(patch_dir):
|
||||||
|
yield
|
||||||
|
|
|
||||||
|
|
@ -155,3 +155,21 @@ def test_get_conflicted_files_non_ascii(in_merge_conflict):
|
||||||
cmd_output('git', 'add', '.')
|
cmd_output('git', 'add', '.')
|
||||||
ret = git.get_conflicted_files()
|
ret = git.get_conflicted_files()
|
||||||
assert ret == {'conflict_file', 'интервью'}
|
assert ret == {'conflict_file', 'интервью'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_intent_to_add(in_git_dir):
|
||||||
|
in_git_dir.join('a').ensure()
|
||||||
|
cmd_output('git', 'add', '--intent-to-add', 'a')
|
||||||
|
|
||||||
|
assert git.intent_to_add_files() == ['a']
|
||||||
|
|
||||||
|
|
||||||
|
def test_status_output_with_rename(in_git_dir):
|
||||||
|
in_git_dir.join('a').write('1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n')
|
||||||
|
cmd_output('git', 'add', 'a')
|
||||||
|
git_commit()
|
||||||
|
cmd_output('git', 'mv', 'a', 'b')
|
||||||
|
in_git_dir.join('c').ensure()
|
||||||
|
cmd_output('git', 'add', '--intent-to-add', 'c')
|
||||||
|
|
||||||
|
assert git.intent_to_add_files() == ['c']
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import shutil
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from pre_commit import git
|
||||||
from pre_commit.staged_files_only import staged_files_only
|
from pre_commit.staged_files_only import staged_files_only
|
||||||
from pre_commit.util import cmd_output
|
from pre_commit.util import cmd_output
|
||||||
from testing.auto_namedtuple import auto_namedtuple
|
from testing.auto_namedtuple import auto_namedtuple
|
||||||
|
|
@ -339,3 +340,14 @@ def test_autocrlf_commited_crlf(in_git_dir, patch_dir):
|
||||||
|
|
||||||
with staged_files_only(patch_dir):
|
with staged_files_only(patch_dir):
|
||||||
assert_no_diff()
|
assert_no_diff()
|
||||||
|
|
||||||
|
|
||||||
|
def test_intent_to_add(in_git_dir, patch_dir):
|
||||||
|
"""Regression test for #881"""
|
||||||
|
_write(b'hello\nworld\n')
|
||||||
|
cmd_output('git', 'add', '--intent-to-add', 'foo')
|
||||||
|
|
||||||
|
assert git.intent_to_add_files() == ['foo']
|
||||||
|
with staged_files_only(patch_dir):
|
||||||
|
assert_no_diff()
|
||||||
|
assert git.intent_to_add_files() == ['foo']
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue