#!/usr/bin/env python """Retrieves commit contents in a patch format. Check README.md for usage examples or run it with `-h` argument to get an interface reference. """ import argparse import os import sys from lib.git import get_patch as git_get_patch def parse_args(): parser = argparse.ArgumentParser( description='Get a commit contents in a patch format.') parser.add_argument('-c', '--commit', nargs='+', required=True, help='Commit hash(es).') parser.add_argument('-f', '--filename', nargs='*', required=False, help='Filename(s) for a patch file(s). Defaults to something like {0}.' .format(get_default_patch_file_name( '4b825dc642cb6eb9a060e54bf8d69288fbee4904'))) parser.add_argument('-o', '--output-dir', required=False, help='Folder to save the patch in. Defaults to a current folder.') parser.add_argument('-r', '--repo', required=True, help='Path to a repository root folder.') args = parser.parse_args() # Additional rules if args.filename is not None and (len(args.commit) != len(args.filename)): parser.error("Number of filenames ({0}) must be equal to number of commits ({1})." .format(len(args.filename), len(args.commit))) return args def get_default_patch_file_name(commit_hash): template = 'backport_{commit_hash}.patch' number_of_hash_characters_to_preserve = 8 commit_hash_string = commit_hash[:number_of_hash_characters_to_preserve+1] patch_file_name = template.format( commit_hash=commit_hash_string) return patch_file_name def get_output_path(output_dir, output_filename, commit_hash): if (output_dir is None) and (output_filename is None): return None # Use current dir as a default. if output_dir is None: output_dir = '.' # Use the default filename if it's not provided. if output_filename is None: output_filename = get_default_patch_file_name(commit_hash) output_path = os.path.join(output_dir, output_filename) return output_path def save_to_file(data, file_path): with open(file_path, 'w') as f: f.write(data) def process_patch(repo, commit_hash, output_path=None): patch_contents = git_get_patch(repo, commit_hash) if output_path is None: sys.stdout.write(patch_contents) else: save_to_file(data=patch_contents, file_path=output_path) def main(): args = parse_args() commits = args.commit filenames = args.filename # (alexeykuzmin): Ugly hack alert. if filenames is None: filenames = [None] * len(commits) for (commit, filename) in zip(commits, filenames): output_path = get_output_path(args.output_dir, filename, commit_hash=commit) process_patch(args.repo, commit, output_path) return 0 if __name__ == '__main__': sys.exit(main())