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

Side by Side Diff: apply_issue.py

Issue 1075723002: Extract authentication options handling into a separate function. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 5 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
« no previous file with comments | « no previous file | auth.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Applies an issue from Rietveld. 6 """Applies an issue from Rietveld.
7 """ 7 """
8 8
9 import getpass 9 import getpass
10 import json 10 import json
11 import logging 11 import logging
12 import optparse 12 import optparse
13 import os 13 import os
14 import subprocess 14 import subprocess
15 import sys 15 import sys
16 import urllib2 16 import urllib2
17 17
18 import breakpad # pylint: disable=W0611 18 import breakpad # pylint: disable=W0611
19 19
20 import annotated_gclient 20 import annotated_gclient
21 import auth
21 import checkout 22 import checkout
22 import fix_encoding 23 import fix_encoding
23 import gclient_utils 24 import gclient_utils
24 import rietveld 25 import rietveld
25 import scm 26 import scm
26 27
27 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 28 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
28 29
29 30
30 class Unbuffered(object): 31 class Unbuffered(object):
(...skipping 18 matching lines...) Expand all
49 help='Prints debugging infos') 50 help='Prints debugging infos')
50 parser.add_option( 51 parser.add_option(
51 '-e', '--email', 52 '-e', '--email',
52 help='Email address to access rietveld. If not specified, anonymous ' 53 help='Email address to access rietveld. If not specified, anonymous '
53 'access will be used.') 54 'access will be used.')
54 parser.add_option( 55 parser.add_option(
55 '-E', '--email-file', 56 '-E', '--email-file',
56 help='File containing the email address to access rietveld. ' 57 help='File containing the email address to access rietveld. '
57 'If not specified, anonymous access will be used.') 58 'If not specified, anonymous access will be used.')
58 parser.add_option( 59 parser.add_option(
59 '-w', '--password',
60 help='Password for email addressed. Use - to read password from stdin. '
61 'if -k is provided, this is the private key file password.')
62 parser.add_option(
63 '-k', '--private-key-file', 60 '-k', '--private-key-file',
64 help='Path to file containing a private key in p12 format for OAuth2 ' 61 help='Path to file containing a private key in p12 format for OAuth2 '
65 'authentication. Use -w to provide the decrypting password, if any.') 62 'authentication with "notasecret" password (as generated by Google '
63 'Cloud Console).')
66 parser.add_option( 64 parser.add_option(
67 '-i', '--issue', type='int', help='Rietveld issue number') 65 '-i', '--issue', type='int', help='Rietveld issue number')
68 parser.add_option( 66 parser.add_option(
69 '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number') 67 '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number')
70 parser.add_option( 68 parser.add_option(
71 '-r', 69 '-r',
72 '--root_dir', 70 '--root_dir',
73 default=os.getcwd(), 71 default=os.getcwd(),
74 help='Root directory to apply the patch') 72 help='Root directory to apply the patch')
75 parser.add_option( 73 parser.add_option(
76 '-s', 74 '-s',
77 '--server', 75 '--server',
78 default='http://codereview.chromium.org', 76 default='http://codereview.chromium.org',
79 help='Rietveld server') 77 help='Rietveld server')
80 parser.add_option('--no-auth', action='store_true', 78 parser.add_option('--no-auth', action='store_true',
81 help='Do not attempt authenticated requests.') 79 help='Do not attempt authenticated requests.')
82 parser.add_option('--revision-mapping', default='{}', 80 parser.add_option('--revision-mapping', default='{}',
83 help='When running gclient, annotate the got_revisions ' 81 help='When running gclient, annotate the got_revisions '
84 'using the revision-mapping.') 82 'using the revision-mapping.')
85 parser.add_option('-f', '--force', action='store_true', 83 parser.add_option('-f', '--force', action='store_true',
86 help='Really run apply_issue, even if .update.flag ' 84 help='Really run apply_issue, even if .update.flag '
87 'is detected.') 85 'is detected.')
88 parser.add_option('-b', '--base_ref', help='DEPRECATED do not use.') 86 parser.add_option('-b', '--base_ref', help='DEPRECATED do not use.')
89 parser.add_option('--whitelist', action='append', default=[], 87 parser.add_option('--whitelist', action='append', default=[],
90 help='Patch only specified file(s).') 88 help='Patch only specified file(s).')
91 parser.add_option('--blacklist', action='append', default=[], 89 parser.add_option('--blacklist', action='append', default=[],
92 help='Don\'t patch specified file(s).') 90 help='Don\'t patch specified file(s).')
93 parser.add_option('-d', '--ignore_deps', action='store_true', 91 parser.add_option('-d', '--ignore_deps', action='store_true',
94 help='Don\'t run gclient sync on DEPS changes.') 92 help='Don\'t run gclient sync on DEPS changes.')
93
94 auth.add_auth_options(parser)
95 options, args = parser.parse_args() 95 options, args = parser.parse_args()
96 auth_config = auth.extract_auth_config_from_options(options)
96 97
97 if options.whitelist and options.blacklist: 98 if options.whitelist and options.blacklist:
98 parser.error('Cannot specify both --whitelist and --blacklist') 99 parser.error('Cannot specify both --whitelist and --blacklist')
99 100
100 if options.password and options.private_key_file:
101 parser.error('-k and -w options are incompatible')
102 if options.email and options.email_file: 101 if options.email and options.email_file:
103 parser.error('-e and -E options are incompatible') 102 parser.error('-e and -E options are incompatible')
104 103
105 if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag')) 104 if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag'))
106 and not options.force): 105 and not options.force):
107 print 'update.flag file found: bot_update has run and checkout is already ' 106 print 'update.flag file found: bot_update has run and checkout is already '
108 print 'in a consistent state. No actions will be performed in this step.' 107 print 'in a consistent state. No actions will be performed in this step.'
109 return 0 108 return 0
110 logging.basicConfig( 109 logging.basicConfig(
111 format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s', 110 format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s',
112 level=[logging.WARNING, logging.INFO, logging.DEBUG][ 111 level=[logging.WARNING, logging.INFO, logging.DEBUG][
113 min(2, options.verbose)]) 112 min(2, options.verbose)])
114 if args: 113 if args:
115 parser.error('Extra argument(s) "%s" not understood' % ' '.join(args)) 114 parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))
116 if not options.issue: 115 if not options.issue:
117 parser.error('Require --issue') 116 parser.error('Require --issue')
118 options.server = options.server.rstrip('/') 117 options.server = options.server.rstrip('/')
119 if not options.server: 118 if not options.server:
120 parser.error('Require a valid server') 119 parser.error('Require a valid server')
121 120
122 options.revision_mapping = json.loads(options.revision_mapping) 121 options.revision_mapping = json.loads(options.revision_mapping)
123 122
124 if options.password == '-':
125 print('Reading password')
126 options.password = sys.stdin.readline().strip()
127
128 # read email if needed 123 # read email if needed
129 if options.email_file: 124 if options.email_file:
130 if not os.path.exists(options.email_file): 125 if not os.path.exists(options.email_file):
131 parser.error('file does not exist: %s' % options.email_file) 126 parser.error('file does not exist: %s' % options.email_file)
132 with open(options.email_file, 'rb') as f: 127 with open(options.email_file, 'rb') as f:
133 options.email = f.read().strip() 128 options.email = f.read().strip()
134 129
135 print('Connecting to %s' % options.server) 130 print('Connecting to %s' % options.server)
136 # Always try un-authenticated first, except for OAuth2 131 # Always try un-authenticated first, except for OAuth2
137 if options.private_key_file: 132 if options.private_key_file:
138 # OAuth2 authentication 133 # OAuth2 authentication
139 obj = rietveld.JwtOAuth2Rietveld(options.server, 134 obj = rietveld.JwtOAuth2Rietveld(options.server,
140 options.email, 135 options.email,
141 options.private_key_file, 136 options.private_key_file)
142 private_key_password=options.password)
143 properties = obj.get_issue_properties(options.issue, False) 137 properties = obj.get_issue_properties(options.issue, False)
144 else: 138 else:
145 obj = rietveld.Rietveld(options.server, '', None) 139 # Passing None as auth_config disables authentication.
140 obj = rietveld.Rietveld(options.server, None)
146 properties = None 141 properties = None
147 # Bad except clauses order (HTTPError is an ancestor class of 142 # Bad except clauses order (HTTPError is an ancestor class of
148 # ClientLoginError) 143 # ClientLoginError)
149 # pylint: disable=E0701 144 # pylint: disable=E0701
150 try: 145 try:
151 properties = obj.get_issue_properties(options.issue, False) 146 properties = obj.get_issue_properties(options.issue, False)
152 except urllib2.HTTPError as e: 147 except urllib2.HTTPError as e:
153 if e.getcode() != 302: 148 if e.getcode() != 302:
154 raise 149 raise
155 if options.no_auth: 150 if options.no_auth:
156 exit('FAIL: Login detected -- is issue private?') 151 exit('FAIL: Login detected -- is issue private?')
157 # TODO(maruel): A few 'Invalid username or password.' are printed first, 152 # TODO(maruel): A few 'Invalid username or password.' are printed first,
158 # we should get rid of those. 153 # we should get rid of those.
159 except rietveld.upload.ClientLoginError, e: 154 except rietveld.upload.ClientLoginError as e:
160 # Fine, we'll do proper authentication. 155 # Fine, we'll do proper authentication.
161 pass 156 pass
162 if properties is None: 157 if properties is None:
163 if options.email is not None: 158 obj = rietveld.Rietveld(options.server, auth_config, options.email)
164 obj = rietveld.Rietveld(options.server, options.email, options.password) 159 try:
165 try: 160 properties = obj.get_issue_properties(options.issue, False)
166 properties = obj.get_issue_properties(options.issue, False) 161 except rietveld.upload.ClientLoginError as e:
167 except rietveld.upload.ClientLoginError, e: 162 print('Accessing the issue requires proper credentials.')
168 if sys.stdout.closed: 163 return 1
169 print('Accessing the issue requires proper credentials.')
170 return 1
171 else:
172 print('Accessing the issue requires login.')
173 obj = rietveld.Rietveld(options.server, None, None)
174 try:
175 properties = obj.get_issue_properties(options.issue, False)
176 except rietveld.upload.ClientLoginError, e:
177 print('Accessing the issue requires proper credentials.')
178 return 1
179 164
180 if not options.patchset: 165 if not options.patchset:
181 options.patchset = properties['patchsets'][-1] 166 options.patchset = properties['patchsets'][-1]
182 print('No patchset specified. Using patchset %d' % options.patchset) 167 print('No patchset specified. Using patchset %d' % options.patchset)
183 168
184 print('Downloading the patch.') 169 print('Downloading the patch.')
185 try: 170 try:
186 patchset = obj.get_patch(options.issue, options.patchset) 171 patchset = obj.get_patch(options.issue, options.patchset)
187 except urllib2.HTTPError, e: 172 except urllib2.HTTPError as e:
188 print( 173 print(
189 'Failed to fetch the patch for issue %d, patchset %d.\n' 174 'Failed to fetch the patch for issue %d, patchset %d.\n'
190 'Try visiting %s/%d') % ( 175 'Try visiting %s/%d') % (
191 options.issue, options.patchset, 176 options.issue, options.patchset,
192 options.server, options.issue) 177 options.server, options.issue)
193 return 1 178 return 1
194 if options.whitelist: 179 if options.whitelist:
195 patchset.patches = [patch for patch in patchset.patches 180 patchset.patches = [patch for patch in patchset.patches
196 if patch.filename in options.whitelist] 181 if patch.filename in options.whitelist]
197 if options.blacklist: 182 if options.blacklist:
(...skipping 17 matching lines...) Expand all
215 # modified. 200 # modified.
216 if options.root_dir == 'src' and getpass.getuser() == 'chrome-bot': 201 if options.root_dir == 'src' and getpass.getuser() == 'chrome-bot':
217 # See sourcedirIsPatched() in: 202 # See sourcedirIsPatched() in:
218 # http://src.chromium.org/viewvc/chrome/trunk/tools/build/scripts/slave/ 203 # http://src.chromium.org/viewvc/chrome/trunk/tools/build/scripts/slave/
219 # chromium_commands.py?view=markup 204 # chromium_commands.py?view=markup
220 open('.buildbot-patched', 'w').close() 205 open('.buildbot-patched', 'w').close()
221 206
222 print('\nApplying the patch.') 207 print('\nApplying the patch.')
223 try: 208 try:
224 scm_obj.apply_patch(patchset, verbose=True) 209 scm_obj.apply_patch(patchset, verbose=True)
225 except checkout.PatchApplicationFailed, e: 210 except checkout.PatchApplicationFailed as e:
226 print(str(e)) 211 print(str(e))
227 print('CWD=%s' % os.getcwd()) 212 print('CWD=%s' % os.getcwd())
228 print('Checkout path=%s' % scm_obj.project_path) 213 print('Checkout path=%s' % scm_obj.project_path)
229 return 1 214 return 1
230 215
231 if ('DEPS' in map(os.path.basename, patchset.filenames) 216 if ('DEPS' in map(os.path.basename, patchset.filenames)
232 and not options.ignore_deps): 217 and not options.ignore_deps):
233 gclient_root = gclient_utils.FindGclientRoot(full_dir) 218 gclient_root = gclient_utils.FindGclientRoot(full_dir)
234 if gclient_root and scm_type: 219 if gclient_root and scm_type:
235 print( 220 print(
(...skipping 24 matching lines...) Expand all
260 return 0 245 return 0
261 246
262 247
263 if __name__ == "__main__": 248 if __name__ == "__main__":
264 fix_encoding.fix_encoding() 249 fix_encoding.fix_encoding()
265 try: 250 try:
266 sys.exit(main()) 251 sys.exit(main())
267 except KeyboardInterrupt: 252 except KeyboardInterrupt:
268 sys.stderr.write('interrupted\n') 253 sys.stderr.write('interrupted\n')
269 sys.exit(1) 254 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | auth.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698