Не так давно решал интересную задачу: нужно было разработать простенький hook-скрипт для git. А если конкретнее, то отслеживать макс.длину измененных строк в файлах, добавленных в текущий коммит. Для этих целей служит специальный хук pre-commit (подробнее о них - тут). Разбираться с gitpy не было времени и желания. К тому же захотелось написать самому.
Оказалось, это не так сложно. Практически все примеры хуков на Python, которые я нашёл в инете - все используют модуль subprocess для работы с git. И вообще, работа с git через Python (и не только) сводится к запуску команд git и парсингу результатов.
Решением стал пакет simplegit, содержащий специальный класс Git():
Примечание: проект тестировался на Ubuntu 12.04 и FreeBSD 9.1, на версии Python 2.7.3
Исходники проекта с инсталляторами и юнит-тестами на github: тут
...
class Git(object):
""" class for a GIT interface
"""
def _call_git(self, *params):
""" call a git command with params
"""
p = subprocess.Popen(
["git"] + list(params),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=False
)
exit_code = p.wait()
if exit_code != 0:
raise GitException("Error: git exit code = %s" % exit_code)
return p.stdout.read().strip()
def config(self, *options):
""" run: git config
"""
return self._call_git("config", *options)
def get_param(self, param, default=None):
""" get one param from git config
"""
try:
res = self.config("--get", param)
return res
except GitException:
return default
def set_param(self, param, value, filename=""):
""" set one param
"""
if filename:
self.config("-f", filename, param, value)
else:
self.config(param, value)
def del_param(self, param):
""" remove parameter
"""
self.config("--unset", param)
def check_git(self):
""" check: git is installed?
"""
try:
self._call_git("--version")
return True
except OSError:
return False
def get_files(self):
""" return a file list... or empty list
"""
ret = self._call_git(
'diff',
'--cached',
'--diff-filter=AM',
'-U0',
'--name-only')
if ret:
return ret.split('\n')
else:
return []
...
Чтобы написать скрипт, реализующий перехватчик (hook) - необходимо создать свой класс, унаследовав его от simplegit.Git и дописав необходимый функционал:
class GitHook(Git):
""" simple git hook for a client side
"""
def check_max_length(self, filename, default_line_length=80):
""" check max length of source lines
"""
# get a config
max_line_length = self.get_param("pre-commit.max-line-length",
default_line_length)
try:
max_line_length = int(max_line_length)
except:
max_line_length = default_line_length
# get a lines and check
for n,s in self.get_diff_rows(filename):
length = len(s)
if length > max_line_length:
print "%s:%d:Line has length %d but %d is allowed" %
(filename, n, length, max_line_length)
print "%s[...]" % s[:80]
return False
return True
def check_file(self, filename):
if self.get_param("pre-commit.max-line-length.enabled") != "false":
res = self.check_max_length(filename)
if not res:
return False
# ... another check-routine place here...
return True
def check(self):
""" check all files in a commit
"""
for filename in self.get_files():
print filename
if not self.check_file(filename):
return False
# ... otherwise check routines place here...
return True
if __name__ == "__main__":
print "[PRE-COMMIT HOOK] Check a files...."
hook = GitHook()
if hook.check():
exit(0)
else:
exit(1)
Примечание: проект тестировался на Ubuntu 12.04 и FreeBSD 9.1, на версии Python 2.7.3
Исходники проекта с инсталляторами и юнит-тестами на github: тут
Спасибо за статью, я немного изменил, чтобы работало в Windows - http://plutov.by/post/git_pre_commit_windows
ОтветитьУдалитьCasinos in India | Wooricasinos
ОтветитьУдалитьWhat is a Casinos in 킹스 포커 India? Indian Casinos 사카미치 마루 - List of all Indian Online 강원 랜드 칩걸 Casinos ✓ Check the best 텐벳 먹튀 Indian Casino Sites ✓ Try for free 아 샤벳 now!