102 lines
		
	
	
	
		
			2.8 KiB
			
		
	
	
	
		
			Text
		
	
	
	
	
	
		
		
			
		
	
	
			102 lines
		
	
	
	
		
			2.8 KiB
			
		
	
	
	
		
			Text
		
	
	
	
	
	
| 
								 | 
							
								#!/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())
							 |