mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-11 13:44:17 +00:00
First commit of file-contents-sorter precommit hook
This commit is contained in:
parent
78818b90cd
commit
9425c5d6b5
5 changed files with 119 additions and 0 deletions
|
|
@ -105,6 +105,12 @@
|
||||||
entry: end-of-file-fixer
|
entry: end-of-file-fixer
|
||||||
language: python
|
language: python
|
||||||
files: \.(asciidoc|adoc|coffee|cpp|css|c|ejs|erb|groovy|h|haml|hh|hpp|hxx|html|in|j2|jade|json|js|less|markdown|md|ml|mli|pp|py|rb|rs|R|scala|scss|sh|slim|tex|tmpl|ts|txt|yaml|yml)$
|
files: \.(asciidoc|adoc|coffee|cpp|css|c|ejs|erb|groovy|h|haml|hh|hpp|hxx|html|in|j2|jade|json|js|less|markdown|md|ml|mli|pp|py|rb|rs|R|scala|scss|sh|slim|tex|tmpl|ts|txt|yaml|yml)$
|
||||||
|
- id: file-contents-sorter
|
||||||
|
name: File Contents Sorter
|
||||||
|
description: Sort the lines in specified files (defaults to alphabetical). You must provide list of target files as input in your .pre-commit-config.yaml file.
|
||||||
|
entry: file-contents-sorter
|
||||||
|
language: python
|
||||||
|
files: ''
|
||||||
- id: fix-encoding-pragma
|
- id: fix-encoding-pragma
|
||||||
name: Fix python encoding pragma
|
name: Fix python encoding pragma
|
||||||
language: python
|
language: python
|
||||||
|
|
|
||||||
57
pre_commit_hooks/file_contents_sorter.py
Normal file
57
pre_commit_hooks/file_contents_sorter.py
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
"""
|
||||||
|
A very simple pre-commit hook that, when passed one or more filenames
|
||||||
|
as arguments, will sort the lines in those files.
|
||||||
|
|
||||||
|
An example use case for this: you have a deploy-whitelist.txt file
|
||||||
|
in a repo that contains a list of filenames that is used to specify
|
||||||
|
files to be included in a docker container. This file has one filename
|
||||||
|
per line. Various users are adding/removing lines from this file; using
|
||||||
|
this hook on that file should reduce the instances of git merge
|
||||||
|
conflicts and keep the file nicely ordered.
|
||||||
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
PASS = 0
|
||||||
|
FAIL = 1
|
||||||
|
|
||||||
|
|
||||||
|
def sort_file_contents(f):
|
||||||
|
before = [line for line in f]
|
||||||
|
after = sorted(before)
|
||||||
|
|
||||||
|
before_string = b''.join(before)
|
||||||
|
after_string = b''.join(after)
|
||||||
|
|
||||||
|
if before_string == after_string:
|
||||||
|
return PASS
|
||||||
|
else:
|
||||||
|
f.seek(0)
|
||||||
|
f.write(after_string)
|
||||||
|
f.truncate()
|
||||||
|
return FAIL
|
||||||
|
|
||||||
|
|
||||||
|
def parse_commandline_input(argv):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('filenames', nargs='+', help='Files to sort')
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv=None):
|
||||||
|
args = parse_commandline_input(argv)
|
||||||
|
|
||||||
|
retv = PASS
|
||||||
|
|
||||||
|
for arg in args.filenames:
|
||||||
|
with open(arg, 'rb+') as file_obj:
|
||||||
|
ret_for_file = sort_file_contents(file_obj)
|
||||||
|
|
||||||
|
if ret_for_file:
|
||||||
|
print('Sorting {}'.format(arg))
|
||||||
|
|
||||||
|
retv |= ret_for_file
|
||||||
|
|
||||||
|
return retv
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
coverage
|
coverage
|
||||||
flake8
|
flake8
|
||||||
|
ipdb
|
||||||
mock
|
mock
|
||||||
pre-commit
|
pre-commit
|
||||||
pytest
|
pytest
|
||||||
|
|
|
||||||
1
setup.py
1
setup.py
|
|
@ -49,6 +49,7 @@ setup(
|
||||||
'detect-private-key = pre_commit_hooks.detect_private_key:detect_private_key',
|
'detect-private-key = pre_commit_hooks.detect_private_key:detect_private_key',
|
||||||
'double-quote-string-fixer = pre_commit_hooks.string_fixer:main',
|
'double-quote-string-fixer = pre_commit_hooks.string_fixer:main',
|
||||||
'end-of-file-fixer = pre_commit_hooks.end_of_file_fixer:end_of_file_fixer',
|
'end-of-file-fixer = pre_commit_hooks.end_of_file_fixer:end_of_file_fixer',
|
||||||
|
'file-contents-sorter = pre_commit_hooks.file_contents_sorter:main',
|
||||||
'fix-encoding-pragma = pre_commit_hooks.fix_encoding_pragma:main',
|
'fix-encoding-pragma = pre_commit_hooks.fix_encoding_pragma:main',
|
||||||
'forbid-new-submodules = pre_commit_hooks.forbid_new_submodules:main',
|
'forbid-new-submodules = pre_commit_hooks.forbid_new_submodules:main',
|
||||||
'name-tests-test = pre_commit_hooks.tests_should_end_in_test:validate_files',
|
'name-tests-test = pre_commit_hooks.tests_should_end_in_test:validate_files',
|
||||||
|
|
|
||||||
54
tests/file_contents_sorter_test.py
Normal file
54
tests/file_contents_sorter_test.py
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
from argparse import ArgumentError
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pre_commit_hooks.file_contents_sorter import FAIL
|
||||||
|
from pre_commit_hooks.file_contents_sorter import main
|
||||||
|
from pre_commit_hooks.file_contents_sorter import parse_commandline_input
|
||||||
|
from pre_commit_hooks.file_contents_sorter import PASS
|
||||||
|
from pre_commit_hooks.file_contents_sorter import sort_file_contents
|
||||||
|
|
||||||
|
|
||||||
|
def _n(*strs):
|
||||||
|
return b'\n'.join(strs) + '\n'
|
||||||
|
|
||||||
|
|
||||||
|
# Input, expected return value, expected output
|
||||||
|
TESTS = (
|
||||||
|
(b'', PASS, b''),
|
||||||
|
(_n('lonesome'), PASS, _n('lonesome')),
|
||||||
|
(b'missing_newline', PASS, b'missing_newline'),
|
||||||
|
(_n('alpha', 'beta'), PASS, _n('alpha', 'beta')),
|
||||||
|
(_n('beta', 'alpha'), FAIL, _n('alpha', 'beta')),
|
||||||
|
(_n('C', 'c'), PASS, _n('C', 'c')),
|
||||||
|
(_n('c', 'C'), FAIL, _n('C', 'c')),
|
||||||
|
(_n('mag ical ', ' tre vor'), FAIL, _n(' tre vor', 'mag ical ')),
|
||||||
|
(_n('@', '-', '_', '#'), FAIL, _n('#', '-', '@', '_')),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(('input_s', 'expected_retval', 'output'), TESTS)
|
||||||
|
def test_integration(input_s, expected_retval, output, tmpdir):
|
||||||
|
path = tmpdir.join('file.txt')
|
||||||
|
path.write_binary(input_s)
|
||||||
|
|
||||||
|
output_retval = main([path.strpath])
|
||||||
|
|
||||||
|
assert path.read_binary() == output
|
||||||
|
assert output_retval == expected_retval
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_commandline_input_errors_without_args():
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
parse_commandline_input([])
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
('filename_list'),
|
||||||
|
(
|
||||||
|
['filename1'],
|
||||||
|
['filename1', 'filename2'],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
def test_parse_commandline_input_success(filename_list):
|
||||||
|
args = parse_commandline_input(filename_list)
|
||||||
|
assert args.filenames == filename_list
|
||||||
Loading…
Add table
Add a link
Reference in a new issue