1#!/usr/bin/env python3
2# Copyright 2020 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"""
7Utility to apply diffs between given two upstream commit hashes to current
8workspace.
9
10This utility diffs files between old_commit and new_commit, with hard-coded
11filter rules, and apply the diff to current HEAD with 3-way-merge supported.
12
13This can be used to uprev a libchrome directory when this is not git history for
14git merge to work.
15"""
16
17import argparse
18import subprocess
19import sys
20
21import filters
22import utils
23
24def main():
25    # Init args
26    parser = argparse.ArgumentParser(
27        description='Copy file from given commits')
28    parser.add_argument(
29        'old_commit', metavar='old_commit', type=str, nargs=1,
30        help='commit hash in upstream branch or browser repository '
31             'we want to uprev from')
32    parser.add_argument(
33        'new_commit', metavar='new_commit', type=str, nargs=1,
34        help='commit hash in upstream branch or browser repository '
35             'we want ot uprev to')
36    parser.add_argument(
37        '--dry_run', dest='dry_run', action='store_const', const=True, default=False)
38    parser.add_argument(
39        '--is_browser', dest='is_browser', action='store_const', const=True, default=False,
40        help='is the commit hash in browser repository')
41    arg = parser.parse_args(sys.argv[1:])
42
43    # Get old and new files.
44    old_files = utils.get_file_list(arg.old_commit[0])
45    new_files = utils.get_file_list(arg.new_commit[0])
46
47    if arg.is_browser:
48        old_files = filters.filter_file([], old_files)
49        new_files = filters.filter_file([], new_files)
50        assert filters.filter_file(old_files, []) == []
51        assert filters.filter_file(new_files, []) == []
52
53    # Generate a tree object for new files.
54    old_tree = utils.git_mktree(old_files)
55    new_tree = utils.git_mktree(new_files)
56    newroot = utils.git_commit(old_tree, [])
57    squashed = utils.git_commit(new_tree, [newroot])
58
59    # Generate patch for git am
60    patch = subprocess.check_output(['git', 'format-patch', '--stdout', newroot+b'..'+squashed])
61
62    if arg.dry_run:
63        print(patch.decode('utf-8'))
64    else:
65        subprocess.run(['git', 'am', '-3'], input=patch)
66
67
68if __name__ == '__main__':
69    main()
70