1 #!/usr/bin/env python 2 # Copyright 2015 the V8 project authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 import argparse 7 import os 8 import sys 9 10 from search_related_commits import git_execute 11 12 GIT_OPTION_HASH_ONLY = '--pretty=format:%H' 13 GIT_OPTION_NO_DIFF = '--quiet' 14 GIT_OPTION_ONELINE = '--oneline' 15 16 def describe_commit(git_working_dir, hash_to_search, one_line=False): 17 if one_line: 18 return git_execute(git_working_dir, ['show', 19 GIT_OPTION_NO_DIFF, 20 GIT_OPTION_ONELINE, 21 hash_to_search]).strip() 22 return git_execute(git_working_dir, ['show', 23 GIT_OPTION_NO_DIFF, 24 hash_to_search]).strip() 25 26 27 def get_followup_commits(git_working_dir, hash_to_search): 28 return git_execute(git_working_dir, ['log', 29 '--grep=' + hash_to_search, 30 GIT_OPTION_HASH_ONLY, 31 'master']).strip().splitlines() 32 33 def get_merge_commits(git_working_dir, hash_to_search): 34 merges = get_related_commits_not_on_master(git_working_dir, hash_to_search) 35 false_merges = get_related_commits_not_on_master( 36 git_working_dir, 'Cr-Branched-From: ' + hash_to_search) 37 false_merges = set(false_merges) 38 return ([merge_commit for merge_commit in merges 39 if merge_commit not in false_merges]) 40 41 def get_related_commits_not_on_master(git_working_dir, grep_command): 42 commits = git_execute(git_working_dir, ['log', 43 '--all', 44 '--grep=' + grep_command, 45 GIT_OPTION_ONELINE, 46 '--decorate', 47 '--not', 48 'master', 49 GIT_OPTION_HASH_ONLY]) 50 return commits.splitlines() 51 52 def get_branches_for_commit(git_working_dir, hash_to_search): 53 branches = git_execute(git_working_dir, ['branch', 54 '--contains', 55 hash_to_search, 56 '-a']).strip() 57 branches = branches.splitlines() 58 return map(str.strip, branches) 59 60 def is_lkgr(git_working_dir, hash_to_search): 61 branches = get_branches_for_commit(git_working_dir, hash_to_search) 62 return 'remotes/origin/lkgr' in branches 63 64 def get_first_canary(git_working_dir, hash_to_search): 65 branches = get_branches_for_commit(git_working_dir, hash_to_search) 66 canaries = ([currentBranch for currentBranch in branches if 67 currentBranch.startswith('remotes/origin/chromium/')]) 68 canaries.sort() 69 if len(canaries) == 0: 70 return 'No Canary coverage' 71 return canaries[0].split('/')[-1] 72 73 def print_analysis(git_working_dir, hash_to_search): 74 print '1.) Searching for "' + hash_to_search + '"' 75 print '=====================ORIGINAL COMMIT START===================' 76 print describe_commit(git_working_dir, hash_to_search) 77 print '=====================ORIGINAL COMMIT END=====================' 78 print '2.) General information:' 79 print 'Is LKGR: ' + str(is_lkgr(git_working_dir, hash_to_search)) 80 print 'Is on Canary: ' + ( 81 str(get_first_canary(git_working_dir, hash_to_search))) 82 print '3.) Found follow-up commits, reverts and ports:' 83 followups = get_followup_commits(git_working_dir, hash_to_search) 84 for followup in followups: 85 print describe_commit(git_working_dir, followup, True) 86 87 print '4.) Found merges:' 88 merges = get_merge_commits(git_working_dir, hash_to_search) 89 for currentMerge in merges: 90 print describe_commit(git_working_dir, currentMerge, True) 91 print '---Merged to:' 92 mergeOutput = git_execute(git_working_dir, ['branch', 93 '--contains', 94 currentMerge, 95 '-r']).strip() 96 print mergeOutput 97 print 'Finished successfully' 98 99 if __name__ == '__main__': # pragma: no cover 100 parser = argparse.ArgumentParser('Tool to check where a git commit was' 101 ' merged and reverted.') 102 103 parser.add_argument('-g', '--git-dir', required=False, default='.', 104 help='The path to your git working directory.') 105 106 parser.add_argument('hash', 107 nargs=1, 108 help='Hash of the commit to be searched.') 109 110 args = sys.argv[1:] 111 options = parser.parse_args(args) 112 113 sys.exit(print_analysis(options.git_dir, options.hash[0])) 114