blob: 9b0cbb9436e13c4753c2eade18fa011420d1c555 [file] [log] [blame]
dchengff845602016-09-23 18:56:191#!/usr/bin/env python
2# Copyright 2016 The Chromium 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"""clang-format 3-way merge driver.
6
7This is a custom merge driver for git that helps automatically resolves
8conflicts caused by clang-format changes. The conflict resolution
9strategy is extremely simple: it simply clang-formats the current,
10ancestor branch's, and other branch's version of the file and delegates
11the remaining work to git merge-file.
12
13See https://git-scm.com/docs/gitattributes ("Defining a custom merge
14driver") for more details.
15"""
16
17import subprocess
18import sys
19
20import clang_format
21
22
23def main():
24 if len(sys.argv) < 5:
25 print('usage: %s <base> <current> <others> <path in the tree>' %
26 sys.argv[0])
27 sys.exit(1)
28
29 base, current, others, file_name_in_tree = sys.argv[1:5]
thakis9bd40a62016-10-01 01:39:1530
31 if file_name_in_tree == '%P':
32 print >>sys.stderr
33 print >>sys.stderr, 'ERROR: clang-format merge driver needs git 2.5+'
34 if sys.platform == 'darwin':
35 print >>sys.stderr, 'Upgrade to Xcode 7.2+'
36 print >>sys.stderr
37 return 1
38
dchengff845602016-09-23 18:56:1939 print 'Running clang-format 3-way merge driver on ' + file_name_in_tree
40
41 try:
42 tool = clang_format.FindClangFormatToolInChromiumTree()
43 for fpath in base, current, others:
44 # Typically, clang-format is used with the -i option to rewrite files
45 # in-place. However, merge files live in the repo root, so --style=file
46 # will always pick up the root .clang-format.
47 #
48 # Instead, this tool uses --assume-filename so clang-format will pick up
49 # the appropriate .clang-format. Unfortunately, --assume-filename only
50 # works when the input is from stdin, so the file I/O portions are lifted
51 # up into the script as well.
52 with open(fpath, 'rb') as input_file:
53 output = subprocess.check_output(
54 [tool, '--assume-filename=%s' % file_name_in_tree, '--style=file'],
55 stdin=input_file)
56 with open(fpath, 'wb') as output_file:
57 output_file.write(output)
58 except clang_format.NotFoundError, e:
59 print e
60 print 'Failed to find clang-format. Falling-back on standard 3-way merge'
61
62 return subprocess.call(['git', 'merge-file', '-Lcurrent', '-Lbase', '-Lother',
63 current, base, others])
64
65
66if __name__ == '__main__':
67 sys.exit(main())