| #!/usr/bin/env python | 
 | # Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. | 
 | # | 
 | # Use of this source code is governed by a BSD-style license | 
 | # that can be found in the LICENSE file in the root of the source | 
 | # tree. An additional intellectual property rights grant can be found | 
 | # in the file PATENTS.  All contributing project authors may | 
 | # be found in the AUTHORS file in the root of the source tree. | 
 |  | 
 | """Script to auto-update the WebRTC source version in call/version.cc""" | 
 |  | 
 | import argparse | 
 | import datetime | 
 | import logging | 
 | import os | 
 | import re | 
 | import subprocess | 
 | import sys | 
 |  | 
 |  | 
 | def FindSrcDirPath(): | 
 |     """Returns the abs path to the src/ dir of the project.""" | 
 |     src_dir = os.path.dirname(os.path.abspath(__file__)) | 
 |     while os.path.basename(src_dir) != 'src': | 
 |         src_dir = os.path.normpath(os.path.join(src_dir, os.pardir)) | 
 |     return src_dir | 
 |  | 
 |  | 
 | UPDATE_BRANCH_NAME = 'webrtc_version_update' | 
 | CHECKOUT_SRC_DIR = FindSrcDirPath() | 
 |  | 
 |  | 
 | def _RemovePreviousUpdateBranch(): | 
 |     active_branch, branches = _GetBranches() | 
 |     if active_branch == UPDATE_BRANCH_NAME: | 
 |         active_branch = 'master' | 
 |     if UPDATE_BRANCH_NAME in branches: | 
 |         logging.info('Removing previous update branch (%s)', | 
 |                      UPDATE_BRANCH_NAME) | 
 |         subprocess.check_call(['git', 'checkout', active_branch]) | 
 |         subprocess.check_call(['git', 'branch', '-D', UPDATE_BRANCH_NAME]) | 
 |     logging.info('No branch to remove') | 
 |  | 
 |  | 
 | def _GetBranches(): | 
 |     """Returns a tuple (active, branches). | 
 |  | 
 |     'active' is a string with name of the currently active branch, while | 
 |      'branches' is the list of all branches. | 
 |     """ | 
 |     lines = subprocess.check_output(['git', 'branch']).splitlines() | 
 |     branches = [] | 
 |     active = '' | 
 |     for line in lines: | 
 |         if '*' in line: | 
 |             # The assumption is that the first char will always be the '*'. | 
 |             active = line[1:].strip() | 
 |             branches.append(active) | 
 |         else: | 
 |             branch = line.strip() | 
 |             if branch: | 
 |                 branches.append(branch) | 
 |     return active, branches | 
 |  | 
 |  | 
 | def _CreateUpdateBranch(): | 
 |     logging.info('Creating update branch: %s', UPDATE_BRANCH_NAME) | 
 |     subprocess.check_call(['git', 'checkout', '-b', UPDATE_BRANCH_NAME]) | 
 |  | 
 |  | 
 | def _UpdateWebRTCVersion(filename): | 
 |     with open(filename) as f: | 
 |         content = f.read() | 
 |     d = datetime.datetime.utcnow() | 
 |     # pylint: disable=line-too-long | 
 |     new_content = re.sub( | 
 |         r'WebRTC source stamp [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}', | 
 |         r'WebRTC source stamp %02d-%02d-%02dT%02d:%02d:%02d' % (d.year, | 
 |                                                                 d.month, | 
 |                                                                 d.day, | 
 |                                                                 d.hour, | 
 |                                                                 d.minute, | 
 |                                                                 d.second), | 
 |         content, | 
 |         flags=re.MULTILINE) | 
 |     # pylint: enable=line-too-long | 
 |     with open(filename, 'w') as f: | 
 |         f.write(new_content) | 
 |  | 
 |  | 
 | def _IsTreeClean(): | 
 |     stdout = subprocess.check_output(['git', 'status', '--porcelain']) | 
 |     if len(stdout) == 0: | 
 |         return True | 
 |     return False | 
 |  | 
 |  | 
 | def _LocalCommit(): | 
 |     logging.info('Committing changes locally.') | 
 |     d = datetime.datetime.utcnow() | 
 |  | 
 |     git_author = subprocess.check_output(['git', 'config', | 
 |                                           'user.email']).strip() | 
 |     tbr_authors = git_author + ',' + 'mbonadei@webrtc.org' | 
 |     tbr = 'TBR=%s' % tbr_authors | 
 |     commit_msg = ('Update WebRTC code version (%02d-%02d-%02dT%02d:%02d:%02d).' | 
 |                   '\n\nTBR=%s\nBug: None') | 
 |     commit_msg = commit_msg % (d.year, d.month, d.day, d.hour, d.minute, | 
 |                                d.second, tbr_authors) | 
 |     subprocess.check_call(['git', 'add', '--update', '.']) | 
 |     subprocess.check_call(['git', 'commit', '-m', commit_msg]) | 
 |  | 
 |  | 
 | def _UploadCL(commit_queue_mode): | 
 |     """Upload the committed changes as a changelist to Gerrit. | 
 |  | 
 |   commit_queue_mode: | 
 |     - 2: Submit to commit queue. | 
 |     - 1: Run trybots but do not submit to CQ. | 
 |     - 0: Skip CQ, upload only. | 
 |   """ | 
 |     cmd = ['git', 'cl', 'upload', '--force', '--bypass-hooks', | 
 |            '--cc=""', '--bypass-watchlist'] | 
 |     if commit_queue_mode >= 2: | 
 |         logging.info('Sending the CL to the CQ...') | 
 |         cmd.extend(['--use-commit-queue']) | 
 |     elif commit_queue_mode >= 1: | 
 |         logging.info('Starting CQ dry run...') | 
 |         cmd.extend(['--cq-dry-run']) | 
 |     subprocess.check_call(cmd) | 
 |  | 
 |  | 
 | def main(): | 
 |     logging.basicConfig(level=logging.INFO) | 
 |     p = argparse.ArgumentParser() | 
 |     p.add_argument('--clean', | 
 |                    action='store_true', | 
 |                    default=False, | 
 |                    help='Removes any previous local update branch.') | 
 |     opts = p.parse_args() | 
 |  | 
 |     if opts.clean: | 
 |         _RemovePreviousUpdateBranch() | 
 |  | 
 |     version_filename = os.path.join(CHECKOUT_SRC_DIR, 'call', 'version.cc') | 
 |     _CreateUpdateBranch() | 
 |     _UpdateWebRTCVersion(version_filename) | 
 |     if _IsTreeClean(): | 
 |         logging.info("No WebRTC version change detected, skipping CL.") | 
 |     else: | 
 |         _LocalCommit() | 
 |         logging.info('Uploading CL...') | 
 |         _UploadCL(2) | 
 |     return 0 | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |   sys.exit(main()) |