#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # SPDX-License-Identifier: Apache-2.0 # Copyright Pionix GmbH and Contributors to EVerest # """ author: andreas.heinrich@rwth-aachen.de Fix author and signoff of commits to match DCO requirements. """ import argparse from pathlib import Path import subprocess def get_git_author_string(args: argparse.Namespace) -> str: try: name = subprocess.run( ['git', '-C', str(args.git_root), 'config', 'user.name'], capture_output=True, text=True, check=True ).stdout.strip() email = subprocess.run( ['git', '-C', str(args.git_root), 'config', 'user.email'], capture_output=True, text=True, check=True ).stdout.strip() except subprocess.CalledProcessError as e: print(f'Git config failed with error: {e.stderr}') exit(1) result = f"{name} <{email}>" return result def remove_signoffs(args: argparse.Namespace) -> str: try: msg_result = subprocess.run( ['git', '-C', str(args.git_root), 'log', '-1', '--pretty=%B'], capture_output=True, text=True, check=True ) except subprocess.CalledProcessError as e: print(f'Git log failed with error: {e.stderr}') exit(1) current_msg = msg_result.stdout lines = current_msg.splitlines() filtered_lines = [ line for line in lines if not line.strip().startswith('Signed-off-by:') ] clean_msg = "\n".join(filtered_lines).strip() return clean_msg def main(): parser = argparse.ArgumentParser( description='Fix author and signoff of latest commit to match DCO requirements.') parser.add_argument( '--author', '-a', type=str, help='Author name and email in the format "Name "', default=None ) parser.add_argument( '--git-root', '-g', type=str, help='Git root directory (default: .)', default=str(Path.cwd()) ) parser.add_argument( '--remove-existing-signoffs', '--rm', action='store_true', help='Remove existing Signed-off-by trailers before adding the new one', default=False ) args = parser.parse_args() args.git_root = Path(args.git_root).expanduser().resolve() if args.author is None: print( "\033[93m" "Warning:\n" " You are overriding the author information with yourself as author.\n" " Please make sure that you are the original author of the commit\n" " or give credits to the original author in commit message by for example\n" " adding a 'Co-authored-by: Original Author ' trailer to the commit message.\n" "\033[0m" ) args.author = get_git_author_string(args) else: print( "\033[93m" "Warning:\n" " You are overriding the author information with a custom value.\n" " You are not allowed to signoff a commit for another person,\n" " except if you are the original author and have the right to do so\n" " or if you are a maintainer fixing the commit for the original author.\n" " For example in case of mismatching user.name and user.email in\n" " case of using github's web based git operations" "\033[0m" ) subprocess_args = [ 'git', '-C', str(args.git_root), 'commit', '--amend', '--no-edit', '--author', args.author, '--trailer', 'Signed-off-by: ' + args.author ] if args.remove_existing_signoffs: clean_msg = remove_signoffs(args) subprocess_args.extend(['-m', clean_msg]) try: subprocess.run( subprocess_args, capture_output=True, text=True, check=True ) except subprocess.CalledProcessError as e: print(f'Git amend failed with error:: {e.stderr}') exit(1) if __name__ == '__main__': main()