Home | History | Annotate | Download | only in release
      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