Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/python -u
      2 # Copyright (c) 2014 The Chromium OS 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 """This module creates the version information of this firmware test suite.
      7 
      8 This module is expected to be executed from the chroot of a host so that
      9 it could extract the git repo information to create the version information.
     10 
     11 The version file contains a pair of a date-time string and a hash like
     12 
     13   version: 2014-01-23.16:18:24 1feddb865cf3f9c158d8cca17a6e68c71b500571
     14 
     15 where the hash is the git hash of the latest patch that satisfies
     16 both conditions:
     17   (1) it could be found in cros/master remote branch on the host, and
     18   (2) it modifies firmware_TouchMTB test,
     19 and the date-time string is the commit time of the above latest patch in the
     20 format of yyyy-mm-dd.hh:mm:ss.
     21 
     22 If the there are any commits on the current local branch on top of the
     23 above latest patch that have modified this test, the version information
     24 will be shown like
     25 
     26 version: revised since 2014-01-23.16:18:24 1feddb865cf3f9c158d8cca17a6e68c71b500
     27 571
     28 
     29 We use "revised since ..." to indicate that some modifications have been made
     30 since the above latest patch.
     31 """
     32 
     33 
     34 import os
     35 import re
     36 import sys
     37 
     38 import common
     39 from common_util import simple_system_output
     40 
     41 
     42 VERSION_FILENAME = '/tmp/.version'
     43 
     44 LOCAL_BR = 'HEAD'
     45 TOT_BR = 'cros/master'
     46 
     47 
     48 def _run_git_cmd(cmd):
     49     """Run git command.
     50 
     51     When a server test is invoked, the present working directory may look
     52     like "/tmp/test_that.xxxx/..."  To be able to run git commands
     53     against the autotest repo, it is required to pushd to autotest project
     54     temporarily.
     55     """
     56     new_cmd = ('pushd %s > /dev/null; %s; popd > /dev/null' %
     57                (common.client_dir, cmd))
     58     return simple_system_output(new_cmd)
     59 
     60 
     61 def _get_common_ancestor(branch_a, branch_b):
     62     """Get the nearest common ancestor of the given branches."""
     63     return _run_git_cmd('git merge-base %s %s' % (branch_a, branch_b))
     64 
     65 
     66 def _get_first_commit_matching_pattern(commit, pattern):
     67     """Get the first commit previous to this commit that matches the pattern."""
     68     cmd = 'git log {} --grep="{}" --pretty=format:"%H" -1'
     69     return _run_git_cmd(cmd.format(commit, pattern))
     70 
     71 
     72 def _get_git_commit(branch):
     73     return _run_git_cmd('git rev-parse %s' % branch)
     74 
     75 
     76 def _get_date_time(commit):
     77     """Get the commit date time in ISO 8601 format."""
     78     cmd = 'git log {} --pretty=format:"%ci" -1'
     79     ts = _run_git_cmd(cmd.format(commit))
     80     date, time, _ = ts.split()
     81     return '%s.%s' % (date, time)
     82 
     83 
     84 def create_version_file(version_filename):
     85     file_path = os.path.dirname(os.path.abspath(sys.modules[__name__].__file__))
     86     result = re.search('site_tests\/(.*?)\/', file_path)
     87     if result is None:
     88         print 'Failed to find the test name.'
     89     test_name = result.group(1)
     90     common_ancestor = _get_common_ancestor(LOCAL_BR, TOT_BR)
     91     latest_test_commit = _get_first_commit_matching_pattern(common_ancestor,
     92                                                             test_name)
     93     date_time_str = _get_date_time(latest_test_commit)
     94 
     95     local_commit = _get_git_commit(LOCAL_BR)
     96     if local_commit == latest_test_commit:
     97         version_template = 'version: %s %s '
     98     else:
     99         version_template = 'version: revised since %s %s '
    100 
    101     version_info = version_template % (date_time_str, latest_test_commit)
    102     with open(version_filename, 'w') as version_file:
    103         version_file.write(version_info)
    104 
    105 
    106 if __name__ == '__main__':
    107     version_filename = sys.argv[1] if len(sys.argv) > 1 else VERSION_FILENAME
    108     create_version_file(version_filename)
    109