11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci"""Writes the most recent "Cr-Commit-Position" value on the master branch 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccito a C header file. 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciUsage: last_commit_position.py <dir> <outfile> <headerguard> 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci <dir> 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Some directory inside the repo to check. This will be used as the current 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci directory when running git. It's best to pass the repo toplevel directory. 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci <outfile> 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci C header file to write. 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci <headerguard> 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci String to use as the header guard for the written file. 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci""" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport os 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport re 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport subprocess 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport sys 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef RunGitCommand(directory, command): 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """ 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Launches git subcommand. 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Errors are swallowed. 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Returns: 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci A process object or None. 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """ 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci command = ['git'] + command 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Force shell usage under cygwin. This is a workaround for 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # mysterious loss of cwd while invoking cygwin's git. 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # We can't just pass shell=True to Popen, as under win32 this will 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # cause CMD to be used, while we explicitly want a cygwin shell. 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if sys.platform == 'cygwin': 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci command = ['sh', '-c', ' '.join(command)] 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proc = subprocess.Popen(command, 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci stdout=subprocess.PIPE, 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci stderr=subprocess.PIPE, 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cwd=directory, 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci shell=(sys.platform=='win32')) 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return proc 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci except OSError: 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return None 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef FetchCommitPosition(directory): 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci regex = re.compile(r'\s*Cr-Commit-Position: refs/heads/master@\{#(\d+)\}\s*') 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Search this far backward in the git log. The commit position should be 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # close to the top. We allow some slop for long commit messages, and maybe 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # there were some local commits after the last "official" one. Having this 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # max prevents us from searching all history in the case of an error. 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci max_lines = 2048 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proc = RunGitCommand(directory, ['log']) 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for i in range(max_lines): 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci line = proc.stdout.readline() 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if not line: 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return None 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci match = regex.match(line) 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if match: 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return match.group(1) 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return None 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef WriteHeader(header_file, header_guard, value): 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci with open(header_file, 'w') as f: 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci f.write('''/* Generated by last_commit_position.py. */ 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#ifndef %(guard)s 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define %(guard)s 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define LAST_COMMIT_POSITION "%(value)s" 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci''' % {'guard': header_guard, 'value': value}) 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciif len(sys.argv) != 4: 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci print "Wrong number of arguments" 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sys.exit(1) 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigit_directory = sys.argv[1] 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccioutput_file = sys.argv[2] 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciheader_guard = sys.argv[3] 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivalue = FetchCommitPosition(git_directory) 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciif not value: 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci print "Could not get last commit position." 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sys.exit(1) 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciWriteHeader(output_file, header_guard, value) 102