Skip to content

Commit

Permalink
Merge pull request #52 from lovato/feature/changedfilesonly
Browse files Browse the repository at this point in the history
Feature/changedfilesonly
  • Loading branch information
lovato committed Apr 26, 2019
2 parents 3888449 + bdc29c0 commit 584a4dc
Show file tree
Hide file tree
Showing 16 changed files with 176 additions and 127 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,5 @@ venv.bak/
# mypy
.mypy_cache/

.vscode
.vscode
node_modules/
19 changes: 13 additions & 6 deletions .hooks4git.ini
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[vars]
STAGED_FILES_IF_ANY = h4g/get_staged_files --format csv --prefix "--filename=" --suffix ""

[scripts]
flake8 = flake8 --max-line-length=119 --exclude .git,build,dist
flake8 = flake8 --max-line-length=119 --exclude .git,build,dist ${STAGED_FILES_IF_ANY}
nosetests = nosetests --with-coverage
pytest = python -m pytest tests
; https://www.npmjs.com/package/travis-lint
travis_linter = travis-lint .travis.yml
; https://github.com/igorshubovych/markdownlint-cli
md_linter = markdownlint README.md
travis_linter = ./node_modules/.bin/travis-lint .travis.yml
md_linter = ./node_modules/.bin/markdownlint README.md
bandit = bandit hooks4git
checkbranch = h4g/check_branch_name ^(feature|bugfix|hotfix|fix)\/.+
black = black . --line-length=119 --check -t py36
Expand All @@ -16,7 +17,13 @@ check = flake8
; check = black

[hooks.pre-push.scripts]
doc_linter = md_linter
tests = pytest
ci_linter = travis_linter
; ci_linter = travis_linter
security = bandit

[hooks.ci.scripts]
doc_linter = md_linter
check = flake8
security = bandit
tests = pytest
36 changes: 22 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
language: python
os:
- linux
# - osx
python:
- '2.7'
- '3.4'
- '3.5'
- '3.6'
cache: pip
# - '3.7'
cache:
- pip
- npm
addons:
apt:
update: true
packages:
- nodejs
- npm
homebrew:
update: true
packages:
- node
before_install:
- sudo apt-get update -qq
- pip install -U pip
- sudo apt-get install nodejs
- sudo apt-get install npm
- curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
- python get-pip.py
install:
- pip install -r requirements.txt
- pip install -r requirements-dev.txt
- npm install -g travis-lint
- npm install -g markdownlint-cli
- npm install
before_script:
- travis-lint .travis.yml
- markdownlint README.md
- pip install .
script:
- flake8 --max-line-length=120 --exclude .git,__pycache__,build,dist
- python -m pytest tests
# - rm -f .hooks4git.yml
# - pip install . -t /tmp
- hooks4git -t ci
after_success:
- coveralls
deploy:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

[![asciicast](https://asciinema.org/a/197368.png)](https://asciinema.org/a/197368)

Fully configurable language-agnostic git hooks.
A fully configurable and extensible language-agnostic Hook Management System for GIT

Auto checks your code before you ship it. Works with any programmning language. If not, let me know.

Expand All @@ -17,7 +17,7 @@ Production version is available from [Pypi](https://pypi.org/project/hooks4git),

### More information on Git Hooks

[Here](https://githooks.com).
[Here](https://githooks.com). There is lots of quick information, and as well other githooks management approaches.

## Getting started

Expand Down
2 changes: 1 addition & 1 deletion hooks4git/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ def __path(filename):
if os.path.exists(__path('build.info')):
__build__ = open(__path('build.info')).read().strip()
if __build__ is None:
__build__ = "dev"
__build__ = "0"

__version__ = __version__ + '.' + __build__
Empty file added hooks4git/h4g/__init__.py
Empty file.
File renamed without changes.
74 changes: 74 additions & 0 deletions hooks4git/h4g/get_staged_files
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
import sys
import argparse


def parse_args(args):
parser = argparse.ArgumentParser(description="Gets staged files from a GIT Repository")

parser.add_argument(
"--prefix",
dest="prefix",
help="String to be added before output",
)
parser.add_argument(
"--suffix",
dest="suffix",
help="String to be added after output",
)
parser.add_argument(
"--format",
dest="format",
help="Defines output format",
)
return parser.parse_args(args)


def system(*args, **kwargs):
"""
Run system command.
"""
result_out = ""
result_err = ""
returncode = -1
try:
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
try:
tmp_out = out.decode('utf-8')
result_out = str(tmp_out)
except Exception as e: # noqa
result_out = str(out)
try:
tmp_err = err.decode('utf-8')
result_err = str(tmp_err)
except Exception as e: # noqa
result_err = str(err)
returncode = proc.returncode
except Exception as e: # noqa
err = str(e)
return returncode, result_out, result_err


def get_staged_files():
git_root = system('git', 'rev-parse', '--show-toplevel')[1].replace('\n', '')
files = []
filelist = system('git', 'diff', '--name-status')[1].replace('\t', ';').split('\n')
filelist.pop()
for line in filelist:
try:
action, filename = line.strip().split(';')
if action != 'D':
files.append("%s/%s" % (git_root, filename))
except Exception as ex: # noqa
pass
return files


if __name__ == "__main__":
args = parse_args(sys.argv[1:])
result = get_staged_files()
if args.format == 'csv':
print("%s%s%s" % (args.prefix, ','.join(result), args.suffix))
54 changes: 13 additions & 41 deletions hooks4git/hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,6 @@ def execute(cmd, files, settings):
"""
Prepare system command.
"""
# if cmd not in ('pep8', 'flake8'):
# raise Exception("Unknown lint command: {}".format(cmd))
args = settings[:]
builtin_path = ""

Expand All @@ -237,8 +235,8 @@ def execute(cmd, files, settings):
# end

cmd_list = cmd.split('/')
git_root = system('git', 'rev-parse', '--show-toplevel')[1].replace('\n', '')
if cmd_list[0] == 'h4g':
git_root = system('git', 'rev-parse', '--show-toplevel')[1].replace('\n', '')
sys.path.insert(0, git_root)
try:
user_site = system('python', '-m', 'site', '--user-site')[1].replace('\n', '')
Expand All @@ -257,16 +255,12 @@ def execute(cmd, files, settings):
pass
for path in sys.path:
builtin_path = os.path.realpath(path + '/hooks4git/h4g/')
ext = 'sh' # if get_platform() in ['Linux', 'Mac', 'WindowsGitBash'] else 'bat'
_cmd = os.path.realpath(os.path.join(builtin_path, cmd_list[1] + '.' + ext))
_cmd = os.path.realpath(os.path.join(builtin_path, cmd_list[1]))
if os.path.exists(_cmd):
cmd = os.path.join(builtin_path, cmd_list[1] + '.' + ext)
# if get_platform() == 'WindowsGitBash':
# cmd = '/' + cmd[0].lower() + cmd[2:].replace('\\','/')
cmd = os.path.join(builtin_path, cmd_list[1])
break

args.insert(0, cmd)
args.extend(files)

display_args = args[1:]

Expand All @@ -276,7 +270,15 @@ def execute(cmd, files, settings):
display_cmd = args[0].replace(builtin_path, "h4g").replace('\\', '/')
args.insert(0, 'bash')

out("STEP", "$ %s %s" % (display_cmd, ' '.join(display_args)))
display_message = "%s %s" % (display_cmd, ' '.join(display_args))

if cmd == 'echo':
if files:
_arg = '--filename=%s' % ','.join(files)
args.append(_arg)
display_message += " " + _arg.replace(git_root, ".")[:(66 - len(display_message))] + "..."

out("STEP", "$ %s" % display_message)

code, result, err = system(*args)
result = result.strip().replace('\n', '\n'.ljust(cmdbarwidth + 1) + '| ')
Expand All @@ -288,33 +290,6 @@ def execute(cmd, files, settings):
return code, result, err


# def get_changed_files():
# """
# Get python files from 'files to commit' git cache list.
# """
# files = []
# # filelist = system('git', 'diff', '--cached', '--name-status')[1]
# filelist = system('git', 'diff', '--name-status')[1]
# for line in filelist:
# try:
# action, filename = line.strip().split()
# if filename.endswith('.py') and action != 'D':
# files.append(filename)
# except Exception as ex: # noqa
# pass
# return files
#
#


# def ini_as_dict(conf):
# d = dict(conf._sections)
# for k in d:
# d[k] = dict(conf._defaults, **d[k])
# d[k].pop('__name__', None)
# return d


def main(cmd):
git_root = system('git', 'rev-parse', '--show-toplevel')[1].replace('\n', '')
configfile = "%s/.hooks4git.ini" % git_root
Expand All @@ -324,7 +299,6 @@ def main(cmd):
try:
config.read(configfile)
cfg = dict(config._sections)
# cfg = ini_as_dict(config)
except Exception as e: # noqa
exception_message = str(e)

Expand All @@ -351,8 +325,7 @@ def main(cmd):
for command_item in commands:
steps_executed += 1
files = []
# if cmd == 'pre-commit':
# files = get_changed_files()
# files = get_changed_files()
command = scripts[hook[command_item]]
result = execute(command.split()[0], files, command.split()[1:])
if result[0] != 0:
Expand Down Expand Up @@ -409,7 +382,6 @@ def divider():

def report():
if steps_executed > 0:
# divider()
end_time = datetime.datetime.now()
if steps_executed > 1:
to_be = 'were'
Expand Down
62 changes: 7 additions & 55 deletions hooks4git/scripts.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,20 @@
# -*- coding: utf-8 -*-

# from setuptools.command.install import install
import sys
import os
import shutil
from hooks4git.hook import system
from hooks4git import __version__
import ast

standalone_run = False


def query_yes_no(question, default="yes"):
"""Ask a yes/no question via raw_input() and return their answer.
"question" is a string that is presented to the user.
"default" is the presumed answer if the user just hits <Enter>.
It must be "yes" (the default), "no" or None (meaning
an answer is required of the user).
The "answer" return value is True for "yes" or False for "no".
"""
valid = {"yes": True, "y": True, "ye": True,
"no": False, "n": False}
if default is None:
prompt = " [y/n] "
elif default == "yes":
prompt = " [Y/n] "
elif default == "no":
prompt = " [y/N] "
else:
raise ValueError("invalid default answer: '%s'" % default)

if sys.version_info[:2] <= (2, 7):
# If this is Python 2, use raw_input()
get_input = ast.literal_eval('raw_input')
else:
get_input = ast.literal_eval('input')

while True:
print('>>>> ' + question + prompt)
choice = get_input().lower()
if default is not None and choice == '':
return valid[default]
elif choice in valid:
return valid[choice]
else:
print("Please respond with 'yes' or 'no' (or 'y' or 'n').\n")


def copy(src, dest):
# print('From: %s' % src)
# print('To: %s' % dest)
if standalone_run:
if os.path.isfile(dest):
# print(dest)
# if query_yes_no('Target file exists. Can I replace it?'):
shutil.copy(src, dest)
# else:
# print('Your file was left untouched. Please consider upgrading it.')
else:
shutil.copy(src, dest)
else:
def copy_file(src, dest):
try:
shutil.copy(src, dest)
return True
except: # noqa
return False


def get_hooks_path(git_root_path):
Expand Down Expand Up @@ -111,13 +63,13 @@ def add_hooks(path=os.environ["PWD"]):
target_config = os.path.join(path, '.hooks4git.ini')
if os.path.isfile(target_config):
target_config = target_config.replace('.ini', '-' + __version__ + '.ini')
copy(origin_config, target_config)
copy_file(origin_config, target_config)
files_to_copy = system('ls', os.path.join(setup_path, 'git/hooks'))
for file in files_to_copy[1].split('\n'):
if file not in ['__pycache__', '', 'hooks4git.py']:
src = os.path.join(setup_path, 'git/hooks', file)
target = os.path.join(git_path, 'hooks', file)
copy(src, target)
copy_file(src, target)
print("Wow! hooks4git files were installed successfully! Thanks for hooking!")
print("If you are a courious person, take a look at .git/hooks folder.")
print("TIP: To get rid of hooks, comment lines on the .hooks4git.ini file.")
Expand Down
Loading

0 comments on commit 584a4dc

Please sign in to comment.