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