Home | History | Annotate | Download | only in gn
      1 # Copyright 2014 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Writes the most recent "Cr-Commit-Position" value on the master branch
      6 to a C header file.
      7 
      8 Usage: last_commit_position.py <dir> <outfile> <headerguard>
      9 
     10   <dir>
     11     Some directory inside the repo to check. This will be used as the current
     12     directory when running git. It's best to pass the repo toplevel directory.
     13 
     14   <outfile>
     15     C header file to write.
     16 
     17   <headerguard>
     18     String to use as the header guard for the written file.
     19 """
     20 
     21 import os
     22 import re
     23 import subprocess
     24 import sys
     25 
     26 def RunGitCommand(directory, command):
     27   """
     28   Launches git subcommand.
     29 
     30   Errors are swallowed.
     31 
     32   Returns:
     33     A process object or None.
     34   """
     35   command = ['git'] + command
     36   # Force shell usage under cygwin. This is a workaround for
     37   # mysterious loss of cwd while invoking cygwin's git.
     38   # We can't just pass shell=True to Popen, as under win32 this will
     39   # cause CMD to be used, while we explicitly want a cygwin shell.
     40   if sys.platform == 'cygwin':
     41     command = ['sh', '-c', ' '.join(command)]
     42   try:
     43     proc = subprocess.Popen(command,
     44                             stdout=subprocess.PIPE,
     45                             stderr=subprocess.PIPE,
     46                             cwd=directory,
     47                             shell=(sys.platform=='win32'))
     48     return proc
     49   except OSError:
     50     return None
     51 
     52 
     53 def FetchCommitPosition(directory):
     54   regex = re.compile(r'\s*Cr-Commit-Position: refs/heads/master@\{#(\d+)\}\s*')
     55 
     56   # Search this far backward in the git log. The commit position should be
     57   # close to the top. We allow some slop for long commit messages, and maybe
     58   # there were some local commits after the last "official" one. Having this
     59   # max prevents us from searching all history in the case of an error.
     60   max_lines = 2048
     61 
     62   proc = RunGitCommand(directory, ['log'])
     63   for i in range(max_lines):
     64     line = proc.stdout.readline()
     65     if not line:
     66       return None
     67 
     68     match = regex.match(line)
     69     if match:
     70       return match.group(1)
     71 
     72   return None
     73 
     74 
     75 def WriteHeader(header_file, header_guard, value):
     76   with open(header_file, 'w') as f:
     77     f.write('''/* Generated by last_commit_position.py. */
     78 
     79 #ifndef %(guard)s
     80 #define %(guard)s
     81 
     82 #define LAST_COMMIT_POSITION "%(value)s"
     83 
     84 #endif
     85 ''' % {'guard': header_guard, 'value': value})
     86 
     87 
     88 if len(sys.argv) != 4:
     89   print "Wrong number of arguments"
     90   sys.exit(1)
     91 
     92 git_directory = sys.argv[1]
     93 output_file = sys.argv[2]
     94 header_guard = sys.argv[3]
     95 
     96 value = FetchCommitPosition(git_directory)
     97 if not value:
     98   print "Could not get last commit position."
     99   sys.exit(1)
    100 
    101 WriteHeader(output_file, header_guard, value)
    102