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 import re 10 11 from search_related_commits import git_execute 12 13 GIT_OPTION_HASH_ONLY = '--pretty=format:%H' 14 GIT_OPTION_NO_DIFF = '--quiet' 15 GIT_OPTION_ONELINE = '--oneline' 16 17 def describe_commit(git_working_dir, hash_to_search, one_line=False): 18 if one_line: 19 return git_execute(git_working_dir, ['show', 20 GIT_OPTION_NO_DIFF, 21 GIT_OPTION_ONELINE, 22 hash_to_search]).strip() 23 return git_execute(git_working_dir, ['show', 24 GIT_OPTION_NO_DIFF, 25 hash_to_search]).strip() 26 27 28 def get_followup_commits(git_working_dir, hash_to_search): 29 cmd = ['log', '--grep=' + hash_to_search, GIT_OPTION_HASH_ONLY, 30 'remotes/origin/master']; 31 return git_execute(git_working_dir, cmd).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 'remotes/origin/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(branches): 61 return 'remotes/origin/lkgr' in branches 62 63 def get_first_canary(branches): 64 canaries = ([currentBranch for currentBranch in branches if 65 currentBranch.startswith('remotes/origin/chromium/')]) 66 canaries.sort() 67 if len(canaries) == 0: 68 return 'No Canary coverage' 69 return canaries[0].split('/')[-1] 70 71 def get_first_v8_version(branches): 72 version_re = re.compile("remotes/origin/[0-9]+\.[0-9]+\.[0-9]+") 73 versions = filter(lambda branch: version_re.match(branch), branches) 74 if len(versions) == 0: 75 return "--" 76 version = versions[0].split("/")[-1] 77 return version 78 79 def print_analysis(git_working_dir, hash_to_search): 80 print '1.) Searching for "' + hash_to_search + '"' 81 print '=====================ORIGINAL COMMIT START===================' 82 print describe_commit(git_working_dir, hash_to_search) 83 print '=====================ORIGINAL COMMIT END=====================' 84 print '2.) General information:' 85 branches = get_branches_for_commit(git_working_dir, hash_to_search) 86 print 'Is LKGR: ' + str(is_lkgr(branches)) 87 print 'Is on Canary: ' + str(get_first_canary(branches)) 88 print 'First V8 branch: ' + str(get_first_v8_version(branches)) + \ 89 ' (Might not be the rolled version)' 90 print '3.) Found follow-up commits, reverts and ports:' 91 followups = get_followup_commits(git_working_dir, hash_to_search) 92 for followup in followups: 93 print describe_commit(git_working_dir, followup, True) 94 95 print '4.) Found merges:' 96 merges = get_merge_commits(git_working_dir, hash_to_search) 97 for currentMerge in merges: 98 print describe_commit(git_working_dir, currentMerge, True) 99 print '---Merged to:' 100 mergeOutput = git_execute(git_working_dir, ['branch', 101 '--contains', 102 currentMerge, 103 '-r']).strip() 104 print mergeOutput 105 print 'Finished successfully' 106 107 if __name__ == '__main__': # pragma: no cover 108 parser = argparse.ArgumentParser('Tool to check where a git commit was' 109 ' merged and reverted.') 110 111 parser.add_argument('-g', '--git-dir', required=False, default='.', 112 help='The path to your git working directory.') 113 114 parser.add_argument('hash', 115 nargs=1, 116 help='Hash of the commit to be searched.') 117 118 args = sys.argv[1:] 119 options = parser.parse_args(args) 120 121 sys.exit(print_analysis(options.git_dir, options.hash[0])) 122