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

Side by Side Diff: tests/sample_pre_commit_hook

Issue 6877055: Move commit-queue/checkout into depot_tools so it can be reused by the try server. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: .gitignore Created 9 years, 8 months 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
« no previous file with comments | « tests/checkout_test.py ('k') | tests/subversion_config/config » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2011 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 at
5 # http://src.chromium.org/viewvc/chrome/trunk/src/LICENSE
6
7 """Commit bot fake author svn server hook.
8
9 Looks for svn commit --withrevprop realauthor=foo, replaces svn:author with this
10 author and sets the property commitbot to the commit bot credential to signify
11 this revision was committed with the commit bot.
12
13 It achieves its goal using an undocumented way. This script could use 'svnlook'
14 to read revprop properties but the code would still be needed to overwrite the
15 properties.
16
17 http://svnbook.red-bean.com/nightly/en/svn.reposadmin.create.html#svn.reposadmin .create.hooks
18 strongly advise against modifying a transation in a commit because the svn
19 client caches certain bits of repository data. Upon asking subversion devs,
20 having the wrong svn:author cached on the commit checkout is the worst that can
21 happen.
22
23 This code doesn't care about this issue because only the commit bot will trigger
24 this code, which runs in a controlled environment.
25
26 The transaction file format is also extremely unlikely to change. If it does,
27 the hook will throw an UnexpectedFileFormat exception which will be silently
28 ignored.
29 """
30
31 import os
32 import re
33 import sys
34
35
36 class UnexpectedFileFormat(Exception):
37 """The transaction file format is not the format expected."""
38
39
40 def read_svn_dump(filepath):
41 """Returns list of (K, V) from a keyed svn file.
42
43 Don't use a map so ordering is kept.
44
45 raise UnexpectedFileFormat if the file cannot be understood.
46 """
47 class InvalidHeaderLine(Exception):
48 """Raised by read_entry when the line read is not the format expected.
49 """
50
51 try:
52 f = open(filepath, 'rb')
53 except EnvironmentError:
54 raise UnexpectedFileFormat('The transaction file cannot be opened')
55
56 try:
57 out = []
58 def read_entry(entrytype):
59 header = f.readline()
60 match = re.match(r'^' + entrytype + ' (\d+)$', header)
61 if not match:
62 raise InvalidHeaderLine(header)
63 datalen = int(match.group(1))
64 data = f.read(datalen)
65 if len(data) != datalen:
66 raise UnpexpectedFileFormat(
67 'Data value is not the expected length')
68 # Reads and ignore \n
69 if f.read(1) != '\n':
70 raise UnpexpectedFileFormat('Data value doesn\'t end with \\n')
71 return data
72
73 while True:
74 try:
75 key = read_entry('K')
76 except InvalidHeaderLine, e:
77 # Check if it's the end of the file.
78 if e.args[0] == 'END\n':
79 break
80 raise UnpexectedFileFormat('Failed to read a key: %s' % e)
81 try:
82 value = read_entry('V')
83 except InvalidHeaderLine, e:
84 raise UnpexectedFileFormat('Failed to read a value: %s' % e)
85 out.append([key, value])
86 return out
87 finally:
88 f.close()
89
90
91 def write_svn_dump(filepath, data):
92 """Writes a svn keyed file with a list of (K, V)."""
93 f = open(filepath, 'wb')
94 try:
95 def write_entry(entrytype, value):
96 f.write('%s %d\n' % (entrytype, len(value)))
97 f.write(value)
98 f.write('\n')
99
100 for k, v in data:
101 write_entry('K', k)
102 write_entry('V', v)
103 f.write('END\n')
104 finally:
105 f.close()
106
107
108 def find_key(data, key):
109 """Finds the item in a list of tuple where item[0] == key.
110
111 asserts if there is more than one item with the key.
112 """
113 items = [i for i in data if i[0] == key]
114 if not items:
115 return None
116 assert len(items) == 1
117 return items[0]
118
119
120 def handle_commit_bot(repo_path, tx, commit_bot, admin_email):
121 """Replaces svn:author with realauthor and sets commit-bot."""
122 # The file format is described there:
123 # http://svn.apache.org/repos/asf/subversion/trunk/notes/dump-load-format.tx t
124 propfilepath = os.path.join(
125 repo_path, 'db', 'transactions', tx + '.txn', 'props')
126
127 # Do a lot of checks to make sure everything is in the expected format.
128 try:
129 data = read_svn_dump(propfilepath)
130 except UnexpectedFileFormat:
131 return (
132 'Failed to parse subversion server transaction format.\n'
133 'Please contact %s ASAP with\n'
134 'this error message.') % admin_email
135 if not data:
136 return (
137 'Failed to load subversion server transaction file.\n'
138 'Please contact %s ASAP with\n'
139 'this error message.') % admin_email
140
141 realauthor = find_key(data, 'realauthor')
142 if not realauthor:
143 # That's fine, there is no author to fake.
144 return
145
146 author = find_key(data, 'svn:author')
147 if not author or not author[1]:
148 return (
149 'Failed to load svn:author from the transaction file.\n'
150 'Please contact %s ASAP with\n'
151 'this error message.') % admin_email
152
153 if author[1] != commit_bot:
154 # The author will not be changed and realauthor will be kept as a
155 # revision property.
156 return
157
158 if len(realauthor[1]) > 50:
159 return 'Fake author was rejected due to being too long.'
160
161 if not re.match(r'^[a-zA-Z0-9\@\-\_\+\%\.]+$', realauthor[1]):
162 return 'Fake author was rejected due to not passing regexp.'
163
164 # Overwrite original author
165 author[1] = realauthor[1]
166 # Remove realauthor svn property
167 data.remove(realauthor)
168 # Add svn property commit-bot=<commit-bot username>
169 data.append(('commit-bot', commit_bot))
170 write_svn_dump(propfilepath, data)
171
172
173 def main():
174 # Replace with your commit-bot credential.
175 commit_bot = 'user1@example.com'
176 admin_email = 'dude@example.com'
177 ret = handle_commit_bot(sys.argv[1], sys.argv[2], commit_bot, admin_email)
178 if ret:
179 print >> sys.stderr, ret
180 return 1
181 return 0
182
183
184 if __name__ == '__main__':
185 sys.exit(main())
186
187 # vim: ts=4:sw=4:tw=80:et:
OLDNEW
« no previous file with comments | « tests/checkout_test.py ('k') | tests/subversion_config/config » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698