add pre-commit hooks

This commit is contained in:
Benjamin Dauvergne 2021-11-25 12:05:38 +01:00
parent e32cda0fba
commit 8e2950e101
2 changed files with 116 additions and 75 deletions

View File

@ -1,24 +1,22 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# pip install --user python-redmine click
from __future__ import print_function
from datetime import datetime, timedelta
import configparser
import glob
import os
import re
import git
import configparser
import unidecode
import tempfile
import glob
import subprocess
import tempfile
from datetime import datetime, timedelta
from requests.adapters import HTTPAdapter
from redminelib import Redmine
import click
import git
import unidecode
from redminelib import Redmine
from requests.adapters import HTTPAdapter
MARKER = '# Everything below is ignored\n'
@ -75,11 +73,11 @@ def get_redmine_api():
redmine.engine.session.mount('http://', HTTPAdapter(max_retries=3))
redmine.engine.session.mount('https://', HTTPAdapter(max_retries=3))
redmine.statuses = {status.name: status for status in redmine.issue_status.all()}
redmine.nouveau = redmine.statuses[u'Nouveau']
redmine.solution = redmine.statuses[u'Solution proposée']
redmine.resolu_a_deployer = redmine.statuses[u'Résolu (à déployer)']
redmine.developpement = [tr for tr in redmine.tracker.all() if tr.name == u'Développement'][0]
redmine.rustine = [cf for cf in redmine.custom_field.all() if cf.name == u'Rustine proposée'][0]
redmine.nouveau = redmine.statuses['Nouveau']
redmine.solution = redmine.statuses['Solution proposée']
redmine.resolu_a_deployer = redmine.statuses['Résolu (à déployer)']
redmine.developpement = [tr for tr in redmine.tracker.all() if tr.name == 'Développement'][0]
redmine.rustine = [cf for cf in redmine.custom_field.all() if cf.name == 'Rustine proposée'][0]
return redmine
@ -101,8 +99,7 @@ def get_issue(issue_number=None):
try:
issue = api.issue.get(issue_number)
except Exception:
raise click.UsageError(
'Cannot find issue %s' % issue_number)
raise click.UsageError('Cannot find issue %s' % issue_number)
return issue
@ -114,8 +111,7 @@ def get_current_issue():
try:
issue_number = int(issue_number)
except Exception:
raise click.UsageError(
'Cannot find an issue number in current branch name %s' % branch_name)
raise click.UsageError('Cannot find an issue number in current branch name %s' % branch_name)
return issue_number
@ -142,14 +138,15 @@ def get_patches(number_of_commits=0, ref=None):
'path': path,
'filename': os.path.basename(path),
}
return list(helper())
@click.group()
def redmine():
'''Integrate git branch with redmine, you must configure your .config/git/config file
with a [redmine] section and keys: url, key or username/password.
'''
"""Integrate git branch with redmine, you must configure your .config/git/config file
with a [redmine] section and keys: url, key or username/password.
"""
pass
@ -161,6 +158,7 @@ def main_branch():
@redmine.command()
def shell():
import IPython
api = get_redmine_api()
repo = get_repo()
IPython.embed()
@ -187,7 +185,9 @@ def apply_attachments(repo, issue):
for i, attachment in enumerate(attachments):
print(i, attachment.created_on, '%6d bytes' % attachment.filesize, attachment.filename)
while True:
indexes = click.prompt('Which patch would you like to apply (id separated by spaces) ?', type=str, default='')
indexes = click.prompt(
'Which patch would you like to apply (id separated by spaces) ?', type=str, default=''
)
try:
indexes = indexes.strip()
if not indexes:
@ -230,8 +230,12 @@ def take(issue_number, reference):
else:
new = True
default_branch_name = 'wip/%s-%s' % (issue_number, slugify(issue.subject)[:32])
click.confirm('Do you want to create a branch tracking %s ?' % (reference or 'origin/%s' % get_main_branch_name()),
default=True, abort=True)
click.confirm(
'Do you want to create a branch tracking %s ?'
% (reference or 'origin/%s' % get_main_branch_name()),
default=True,
abort=True,
)
branch_name = click.prompt('Branch name', default=default_branch_name)
branch = repo.create_head(branch_name, commit=reference or 'origin/%s' % get_main_branch_name())
set_branch_option(repo, branch, 'merge', 'refs/heads/%s' % get_main_branch_name())
@ -242,9 +246,10 @@ def take(issue_number, reference):
branch.checkout()
click.echo('Moved to branch %s' % branch_name)
current_user = api.user.get('current')
if ((not hasattr(issue, 'assigned_to') or issue.assigned_to.id != current_user.id)
and click.confirm('Do you want to assign the issue to yourself ?',
default=not hasattr(issue, 'assigned_to') and issue.status == api.nouveau)):
if (not hasattr(issue, 'assigned_to') or issue.assigned_to.id != current_user.id) and click.confirm(
'Do you want to assign the issue to yourself ?',
default=not hasattr(issue, 'assigned_to') and issue.status == api.nouveau,
):
issue.assigned_to_id = current_user.id
issue.save()
if new:
@ -303,8 +308,13 @@ def submit(ctx, issue, no_rebase, number_of_commits):
origin = repo.remote()
for pi in origin.push(f=True):
if pi.flags & pi.ERROR:
click.echo(click.style(u'Push from « %s » to « %s » failed.' % (
pi.local_ref.name, pi.remote_ref.name, pi.summary), fg='red'))
click.echo(
click.style(
'Push from « %s » to « %s » failed.'
% (pi.local_ref.name, pi.remote_ref.name, pi.summary),
fg='red',
)
)
if click.confirm('Propose this patch as a solution ?', default=True):
current_user = api.user.get('current')
@ -312,15 +322,21 @@ def submit(ctx, issue, no_rebase, number_of_commits):
issue.assigned_to_id = current_user.id
issue.save()
elif issue.assigned_to.id != current_user.id:
if click.confirm('Issue is currently assigned to %s, do you want '
'to assign the issue to yourself ?' % issue.assigned_to.name):
if click.confirm(
'Issue is currently assigned to %s, do you want '
'to assign the issue to yourself ?' % issue.assigned_to.name
):
issue.assigned_to_id = current_user.id
issue.save()
kwargs['tracker_id'] = api.developpement.id
kwargs['status_id'] = api.solution.id
api.issue.update(issue.id, notes=message, uploads=patches,
custom_fields=[{'id': api.rustine.id, 'value': u'1'}],
**kwargs)
api.issue.update(
issue.id,
notes=message,
uploads=patches,
custom_fields=[{'id': api.rustine.id, 'value': '1'}],
**kwargs,
)
@issue.command()
@ -360,7 +376,8 @@ def new(ctx, reference):
subject=subject,
tracker_id=api.developpement.id,
description=description,
assigned_to_id=current_user.id)
assigned_to_id=current_user.id,
)
click.echo('Created issue %s' % issue.url)
ctx.invoke(take, issue_number=issue.id, reference=reference)
@ -374,16 +391,18 @@ def link(issue):
try:
target_issue = api.issue.get(issue)
except Exception:
raise click.UsageError(
'Cannot find issue %s' % issue)
raise click.UsageError('Cannot find issue %s' % issue)
if len(api.issue_relation.filter(issue_id=current_issue.id, issue_to_id=target_issue.id)):
click.echo(click.style('Already linked.', fg='green'))
return
if click.confirm(f'Link issue {current_issue.id } - « {current_issue.subject} » to {target_issue.id} - « {target_issue.subject} »', default=False, abort=True):
if click.confirm(
f'Link issue {current_issue.id } - « {current_issue.subject} » to {target_issue.id} - « {target_issue.subject} »',
default=False,
abort=True,
):
api.issue_relation.create(
issue_id=current_issue.id,
issue_to_id=target_issue.id,
relation_type='relates')
issue_id=current_issue.id, issue_to_id=target_issue.id, relation_type='relates'
)
click.echo(click.style('Linked.', fg='green'))
@ -393,8 +412,7 @@ class MyProgressPrinter(git.RemoteProgress):
def get_commits(repo, ref):
for commit in git.Commit.iter_items(repo, '%s..' % ref):
yield commit
yield from git.Commit.iter_items(repo, '%s..' % ref)
@redmine.command(name='merge-and-push')
@ -426,7 +444,7 @@ def merge_and_push(issue, validate_msg, target_branch):
if validate_msg:
for commit in get_commits(repo, target_branch):
if (u'#%s' % get_current_issue()) not in commit.message:
if ('#%s' % get_current_issue()) not in commit.message:
click.echo(click.style('Missing commit number in commit message', fg='red'))
click.echo()
click.echo(commit.message)
@ -440,26 +458,30 @@ def merge_and_push(issue, validate_msg, target_branch):
click.confirm('Continue ?', abort=True)
try:
click.echo(u'Checking-out branch « %s » ... ' % target_branch, nl=False)
click.echo('Checking-out branch « %s » ... ' % target_branch, nl=False)
repo.branches[target_branch].checkout()
click.echo(click.style('Done.', fg='green'))
click.echo(u'Pull-rebasing from remote « %s » onto branch « %s » ... ' % (origin.name, target_branch), nl=False)
click.echo(
'Pull-rebasing from remote « %s » onto branch « %s » ... ' % (origin.name, target_branch),
nl=False,
)
failure = False
for pi in origin.pull(rebase=True):
if pi.flags & pi.ERROR:
failure = True
click.echo(click.style(u'Pull-rebase from « %s » failed: %s.' % (
pi.ref.name, pi.note), fg='red'))
click.echo(
click.style('Pull-rebase from « %s » failed: %s.' % (pi.ref.name, pi.note), fg='red')
)
click.echo(click.style('Done.', fg='green'))
if failure:
raise click.ClickException('Pull rebase failed.')
finally:
click.echo(u'Checking-out branch « %s »... ' % current_head, nl=False)
click.echo('Checking-out branch « %s »... ' % current_head, nl=False)
repo.branches[current_head].checkout()
click.echo(click.style('Done.', fg='green'))
try:
click.echo(u'Rebasing branch « %s » onto branch « %s » ... ' % (current_head, target_branch), nl=False)
click.echo('Rebasing branch « %s » onto branch « %s » ... ' % (current_head, target_branch), nl=False)
repo.git.rebase(target_branch)
except git.GitCommandError as e:
click.echo(click.style('command %r failed, aborting.' % e.command, fg='red'))
@ -473,7 +495,7 @@ def merge_and_push(issue, validate_msg, target_branch):
click.echo('Checking-out to %s... ' % target_branch, nl=False)
repo.branches[target_branch].checkout()
click.echo(click.style('Done.', fg='green'))
click.echo(u'Merging branch « %s » into « %s » ... ' % (current_head, target_branch), nl=False)
click.echo('Merging branch « %s » into « %s » ... ' % (current_head, target_branch), nl=False)
try:
repo.git.merge(current_head, ff=True)
except git.GitCommandError as e:
@ -490,24 +512,39 @@ def merge_and_push(issue, validate_msg, target_branch):
except IndexError:
pass
else:
if click.confirm(u'Do you want to delete feature branch « %s » on remote « %s » ?' % (
current_head, origin.name), default=True):
if click.confirm(
'Do you want to delete feature branch « %s » on remote « %s » ?'
% (current_head, origin.name),
default=True,
):
for pi in origin.push(refspec=':%s' % current_head):
if pi.flags & pi.ERROR:
click.echo(click.style(u'Push from « %s » to « %s » failed.' % (
pi.local_ref.name, pi.remote_ref.name, pi.summary), fg='red'))
if click.confirm(u'Do you want to push « %s » on remote « %s » ?' % (target_branch, repo.remote().name),
default=True):
click.echo(
click.style(
'Push from « %s » to « %s » failed.'
% (pi.local_ref.name, pi.remote_ref.name, pi.summary),
fg='red',
)
)
if click.confirm(
'Do you want to push « %s » on remote « %s » ?' % (target_branch, repo.remote().name),
default=True,
):
for pi in origin.push():
if pi.flags & pi.ERROR:
click.echo(click.style(u'Push from « %s » to « %s » failed: %s.' % (
pi.local_ref.name, pi.remote_ref.name, pi.summary), fg='red'))
if click.confirm(u'Do you want to delete feature branch « %s » ?' % current_head, default=True):
click.echo(
click.style(
'Push from « %s » to « %s » failed: %s.'
% (pi.local_ref.name, pi.remote_ref.name, pi.summary),
fg='red',
)
)
if click.confirm('Do you want to delete feature branch « %s » ?' % current_head, default=True):
repo.delete_head(repo.branches[current_head])
else:
repo.branches[current_head].checkout()
except Exception:
click.echo(click.style(u'\nFailure going back to branch « %s ».' % current_head, fg='red'))
click.echo(click.style('\nFailure going back to branch « %s ».' % current_head, fg='red'))
repo.branches[current_head].checkout()
raise
if click.confirm('Set issue status to solved ?', default=True):
@ -518,8 +555,10 @@ def merge_and_push(issue, validate_msg, target_branch):
issue.assigned_to_id = current_user.id
issue.save()
elif issue.assigned_to.id != current_user.id:
if click.confirm('Issue is currently assigned to %s, do you want '
'to assign the issue to yourself ?' % issue.assigned_to.name):
if click.confirm(
'Issue is currently assigned to %s, do you want '
'to assign the issue to yourself ?' % issue.assigned_to.name
):
issue.assigned_to_id = current_user.id
issue.save()
kwargs['status_id'] = api.resolu_a_deployer.id
@ -541,7 +580,7 @@ def rebase(target_branch):
current_head = repo.head.ref.name
if current_head == target_branch:
raise click.UsageError(u'Your cannot rebase on « %s » as your are already on it.' % target_branch)
raise click.UsageError('Your cannot rebase on « %s » as your are already on it.' % target_branch)
try:
repo.branches[target_branch]
@ -549,26 +588,30 @@ def rebase(target_branch):
raise click.UsageError('%r is not a local branch.' % target_branch)
try:
click.echo(u'Checking-out branch « %s » ... ' % target_branch, nl=False)
click.echo('Checking-out branch « %s » ... ' % target_branch, nl=False)
repo.branches[target_branch].checkout()
click.echo(click.style('Done.', fg='green'))
click.echo(u'Pull-rebasing from remote « %s » onto branch « %s » ... ' % (origin.name, target_branch), nl=False)
click.echo(
'Pull-rebasing from remote « %s » onto branch « %s » ... ' % (origin.name, target_branch),
nl=False,
)
failure = False
for pi in origin.pull(rebase=True):
if pi.flags & pi.ERROR:
failure = True
click.echo(click.style(u'Pull-rebase from « %s » failed: %s.' % (
pi.ref.name, pi.note), fg='red'))
click.echo(
click.style('Pull-rebase from « %s » failed: %s.' % (pi.ref.name, pi.note), fg='red')
)
click.echo(click.style('Done.', fg='green'))
if failure:
raise click.ClickException('Pull rebase failed.')
finally:
click.echo(u'Checking-out branch « %s »... ' % current_head, nl=False)
click.echo('Checking-out branch « %s »... ' % current_head, nl=False)
repo.branches[current_head].checkout()
click.echo(click.style('Done.', fg='green'))
try:
click.echo(u'Rebasing branch « %s » onto branch « %s » ... ' % (current_head, target_branch), nl=False)
click.echo('Rebasing branch « %s » onto branch « %s » ... ' % (current_head, target_branch), nl=False)
repo.git.rebase(target_branch)
except git.GitCommandError as e:
click.echo(click.style('command %r failed, aborting.' % e.command, fg='red'))
@ -626,9 +669,7 @@ def clean():
temp_issues_to_branch = list(issues_to_branch)
while temp_issues_to_branch:
issue_ids = ','.join(temp_issues_to_branch[:30])
issues = api.issue.filter(issue_id=issue_ids,
status_id='closed',
include=['journals'])
issues = api.issue.filter(issue_id=issue_ids, status_id='closed', include=['journals'])
for issue in issues:
journals = list(issue.journals)
last_journal = len(journals) and journals[len(journals) - 1]

View File

@ -23,5 +23,5 @@ setup(
],
entry_points={
'console_scripts': ['git-redmine=git_redmine:redmine'],
}
},
)