Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(434)

Side by Side Diff: scripts/slave/patch_path_filter.py

Issue 27575002: Patch path filtering script. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Simplified after discovering upload.py stuff, and more tests! Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright 2013 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
6 """Script that can be used to filter out files from a patch/diff.
7
8 Usage: pipe the patch contents to stdin and the filtered output will be written
9 to stdout.
10 The output will be compatible with the patch program, both for Subversion and
11 Git patches.
12 NOTICE: the script can only manage patches created by depot tools (i.e. it
13 is supposed to be used for tryjob generated patches. This is because it relies
14 no the Index: line being present, which is normally not the case for Git patches
15 (it is added by depot_tools/third_party/upload.py during the creation of the
16 try job).
17 """
18
19 import optparse
20 import os
21 import re
22 import sys
23
24 from depot_tools import patch
25
26
27 def parse_patch_set(patch_contents):
28 patch_chunks = []
29 current_chunk = []
30 for line in patch_contents.splitlines(True):
31 # See https://code.google.com/p/chromium/codesearch#
32 # chromium/tools/depot_tools/third_party/upload.py
33 # for details on how patches uploaded with depot_tools will have each
34 # file chunk start with either of these strings (for both Git and SVN).
35 if ((line.startswith('Index:') or line.startswith('Property changes on:'))
iannucci 2013/12/10 21:32:23 FYI, you can do line.startswith(('Index:', 'Prop
kjellander_chromium 2013/12/11 13:31:31 Thanks, fixed.
36 and current_chunk):
37 patch_chunks.insert(0, current_chunk)
38 current_chunk = []
39 current_chunk.append(line)
40
41 if current_chunk:
42 patch_chunks.insert(0, current_chunk)
43
44 # Parse filename for each patch chunk and create FilePatchDiff objects
45 filename_regex = re.compile(r'^.*: ([^\t]+).*\n$')
iannucci 2013/12/10 21:32:23 I would put this up in the global scope as FILENAM
kjellander_chromium 2013/12/11 13:31:31 Done.
46 patches = []
47 for chunk in patch_chunks:
48 match = filename_regex.match(chunk[0])
49 if not match:
50 raise Exception('Did not find any filename in line "%s". Notice that '
51 'only patches uploaded using depot tools are supported '
52 'since normal Git patches don\'t include the "Index:" '
53 'line.' % chunk[0])
54 filename = match.group(1).replace('\\', '/')
55 patches.append(patch.FilePatchDiff(filename=filename, diff=''.join(chunk),
56 svn_properties=[]))
57 return patch.PatchSet(patches)
58
59
60 def convert_to_patch_compatible_diff(filename, patch_data):
kjellander_chromium 2013/12/10 20:46:03 When doing testing on actual checkouts with the ap
61 """Convert patch data to be compatible with the standard patch program.
62
63 This will remove the "a/" and "b/" prefixes added by Git, so the patch becomes
64 compatible with the standard patch program.
iannucci 2013/12/10 21:32:23 you could also just pass -p1 to patch.
kjellander_chromium 2013/12/11 13:31:31 I could if I knew when invoking the patch program
65 """
66 diff = ''
67 for line in patch_data.splitlines(True):
68 if line.startswith('---'):
69 line = line.replace('a/' + filename, filename)
70 if line.startswith('+++'):
iannucci 2013/12/10 21:32:23 elif? though obviously both won't hit, but it may
kjellander_chromium 2013/12/11 13:31:31 Done.
71 line = line.replace('b/' + filename, filename)
72 diff += line
73 return diff
74
75
76 def main():
77 usage = '%s -f <path-filter> [-r <root-dir>]' % os.path.basename(sys.argv[0])
78 parser = optparse.OptionParser(usage=usage)
79 parser.add_option('-f', '--path-filter',
80 help=('The path filter (UNIX paths) that all file paths '
81 'are required to have to pass this filter (no '
82 'regexp).'))
83 parser.add_option('-r', '--root-dir',
84 help=('The patch root dir in which to apply the patch. If '
85 'specified, it will be prepended to the filename '
86 'for each patch entry before the filter is applied.'))
87
88 options, args = parser.parse_args()
89 if args:
90 parser.error('Unused args: %s' % args)
91 if not options.path_filter:
92 parser.error('A path filter must be be specified.')
93
94 patch_contents = sys.stdin.read()
95
96 # Only print the patch entries that passes our path filter.
97 for patch_entry in parse_patch_set(patch_contents):
98 filename = patch_entry.filename
99 if options.root_dir:
100 filename = os.path.join(options.root_dir, filename)
101
102 if filename.startswith(options.path_filter):
103 print convert_to_patch_compatible_diff(patch_entry.filename,
104 patch_entry.get(for_git=False)),
105
106 if __name__ == '__main__':
107 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698