Chromium Code Reviews

Side by Side Diff: apply_issue.py

Issue 183793010: Added OAuth2 authentication to apply_issue (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Added another option Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « no previous file | rietveld.py » ('j') | rietveld.py » ('J')
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
(...skipping 33 matching lines...)
44 sys.stdout = Unbuffered(sys.stdout) 44 sys.stdout = Unbuffered(sys.stdout)
45 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) 45 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
46 parser.add_option( 46 parser.add_option(
47 '-v', '--verbose', action='count', default=0, 47 '-v', '--verbose', action='count', default=0,
48 help='Prints debugging infos') 48 help='Prints debugging infos')
49 parser.add_option( 49 parser.add_option(
50 '-e', '--email', 50 '-e', '--email',
51 help='Email address to access rietveld. If not specified, anonymous ' 51 help='Email address to access rietveld. If not specified, anonymous '
52 'access will be used.') 52 'access will be used.')
53 parser.add_option( 53 parser.add_option(
54 '-E', '--email-file',
55 help='File containing the email address to access rietveld. '
56 'If not specified, anonymous access will be used.')
57 parser.add_option(
54 '-w', '--password', default=None, 58 '-w', '--password', default=None,
M-A Ruel 2014/03/13 01:31:27 Remove this one while at it.
pgervais 2014/03/13 22:38:38 I think we're still using it for the public rietve
55 help='Password for email addressed. Use - to read password from stdin.') 59 help='Password for email addressed. Use - to read password from stdin. '
60 'Incompatible with -k')
M-A Ruel 2014/03/13 01:31:27 prefer to keep alignment consistent.
pgervais 2014/03/13 22:38:38 Done.
61 parser.add_option(
62 '-k', '--private-key-file', default=None,
M-A Ruel 2014/03/13 01:31:27 default=None is the default, no need to specify it
pgervais 2014/03/13 22:38:38 alright, but explicit is better than implicit. Don
63 help='Path to file containing a private key in p12 format for OAuth2 '
M-A Ruel 2014/03/13 01:31:27 You mean for a service account? That would be for
pgervais 2014/03/13 22:38:38 It is indeed for the bots. No user will use that.
64 'authentication. Incompatible with -w.')
56 parser.add_option( 65 parser.add_option(
57 '-i', '--issue', type='int', help='Rietveld issue number') 66 '-i', '--issue', type='int', help='Rietveld issue number')
58 parser.add_option( 67 parser.add_option(
59 '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number') 68 '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number')
60 parser.add_option( 69 parser.add_option(
61 '-r', 70 '-r',
62 '--root_dir', 71 '--root_dir',
63 default=os.getcwd(), 72 default=os.getcwd(),
64 help='Root directory to apply the patch') 73 help='Root directory to apply the patch')
65 parser.add_option( 74 parser.add_option(
66 '-s', 75 '-s',
67 '--server', 76 '--server',
68 default='http://codereview.chromium.org', 77 default='http://codereview.chromium.org',
69 help='Rietveld server') 78 help='Rietveld server')
70 parser.add_option('--no-auth', action='store_true', 79 parser.add_option('--no-auth', action='store_true',
71 help='Do not attempt authenticated requests.') 80 help='Do not attempt authenticated requests.')
72 parser.add_option('--revision-mapping', default='{}', 81 parser.add_option('--revision-mapping', default='{}',
73 help='When running gclient, annotate the got_revisions ' 82 help='When running gclient, annotate the got_revisions '
74 'using the revision-mapping.') 83 'using the revision-mapping.')
75 parser.add_option('-f', '--force', action='store_true', 84 parser.add_option('-f', '--force', action='store_true',
76 help='Really run apply_issue, even if .update.flag ' 85 help='Really run apply_issue, even if .update.flag '
77 'is detected.') 86 'is detected.')
78 parser.add_option('-b', '--base_ref', help='Base git ref to patch on top of, ' 87 parser.add_option('-b', '--base_ref', help='Base git ref to patch on top of, '
79 'used for verification.') 88 'used for verification.')
80 options, args = parser.parse_args() 89 options, args = parser.parse_args()
90
91 if options.password and options.private_key_file:
92 parser.error('-k and -w options are incompatible')
93 if options.email and options.email_file:
94 parser.error('-e and -E options are incompatible')
95
81 if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag')) 96 if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag'))
82 and not options.force): 97 and not options.force):
83 print 'update.flag file found: bot_update has run and checkout is already ' 98 print 'update.flag file found: bot_update has run and checkout is already '
84 print 'in a consistent state. No actions will be performed in this step.' 99 print 'in a consistent state. No actions will be performed in this step.'
85 return 0 100 return 0
86 logging.basicConfig( 101 logging.basicConfig(
87 format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s', 102 format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s',
88 level=[logging.WARNING, logging.INFO, logging.DEBUG][ 103 level=[logging.WARNING, logging.INFO, logging.DEBUG][
89 min(2, options.verbose)]) 104 min(2, options.verbose)])
90 if args: 105 if args:
91 parser.error('Extra argument(s) "%s" not understood' % ' '.join(args)) 106 parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))
92 if not options.issue: 107 if not options.issue:
93 parser.error('Require --issue') 108 parser.error('Require --issue')
94 options.server = options.server.rstrip('/') 109 options.server = options.server.rstrip('/')
95 if not options.server: 110 if not options.server:
96 parser.error('Require a valid server') 111 parser.error('Require a valid server')
97 112
98 options.revision_mapping = json.loads(options.revision_mapping) 113 options.revision_mapping = json.loads(options.revision_mapping)
99 114
100 if options.password == '-': 115 if options.password == '-':
101 print('Reading password') 116 print('Reading password')
102 options.password = sys.stdin.readline().strip() 117 options.password = sys.stdin.readline().strip()
103 118
119 # read email if needed
120 if options.email_file:
121 if not os.path.exists(options.email_file):
122 print('file does not exist: %s' % str(options.email_file))
M-A Ruel 2014/03/13 01:31:27 parser.error() Then you don't need to return.
M-A Ruel 2014/03/13 01:31:27 No need to str().
pgervais 2014/03/13 22:38:38 Done.
123 return 1
124 with open(options.email_file, 'rb') as f:
125 options.email = f.read().strip()
126
104 print('Connecting to %s' % options.server) 127 print('Connecting to %s' % options.server)
105 # Always try un-authenticated first. 128 # Always try un-authenticated first, except for OAuth2
106 # TODO(maruel): Use OAuth2 properly so we don't hit rate-limiting on login 129 if options.private_key_file:
107 # attempts. 130 # OAuth2 authentication
108 # Bad except clauses order (HTTPError is an ancestor class of 131 obj = rietveld.OAuthRietveld(options.server,
109 # ClientLoginError) 132 options.email,
110 # pylint: disable=E0701 133 options.private_key_file,
111 obj = rietveld.Rietveld(options.server, '', None) 134 private_key_password=options.password)
112 properties = None
113 try:
114 properties = obj.get_issue_properties(options.issue, False) 135 properties = obj.get_issue_properties(options.issue, False)
115 except urllib2.HTTPError, e: 136 else:
116 if e.getcode() != 302: 137 obj = rietveld.Rietveld(options.server, '', None)
117 raise 138 properties = None
118 elif options.no_auth: 139 # Bad except clauses order (HTTPError is an ancestor class of
119 exit('FAIL: Login detected -- is issue private?') 140 # ClientLoginError)
120 # TODO(maruel): A few 'Invalid username or password.' are printed first, we 141 # pylint: disable=E0701
121 # should get rid of those. 142 try:
122 except rietveld.upload.ClientLoginError, e: 143 properties = obj.get_issue_properties(options.issue, False)
123 # Fine, we'll do proper authentication. 144 except urllib2.HTTPError, e:
124 pass 145 if e.getcode() != 302:
125 if properties is None: 146 raise
126 if options.email is not None: 147 elif options.no_auth:
127 obj = rietveld.Rietveld(options.server, options.email, options.password) 148 exit('FAIL: Login detected -- is issue private?')
128 try: 149 # TODO(maruel): A few 'Invalid username or password.' are printed first,
129 properties = obj.get_issue_properties(options.issue, False) 150 # we should get rid of those.
130 except rietveld.upload.ClientLoginError, e: 151 except rietveld.upload.ClientLoginError, e:
131 if sys.stdout.closed: 152 # Fine, we'll do proper authentication.
153 pass
154 if properties is None:
155 if options.email is not None:
156 obj = rietveld.Rietveld(options.server, options.email, options.password)
157 try:
158 properties = obj.get_issue_properties(options.issue, False)
159 except rietveld.upload.ClientLoginError, e:
160 if sys.stdout.closed:
161 print('Accessing the issue requires proper credentials.')
162 return 1
163 else:
164 print('Accessing the issue requires login.')
165 obj = rietveld.Rietveld(options.server, None, None)
166 try:
167 properties = obj.get_issue_properties(options.issue, False)
168 except rietveld.upload.ClientLoginError, e:
132 print('Accessing the issue requires proper credentials.') 169 print('Accessing the issue requires proper credentials.')
133 return 1 170 return 1
134 else:
135 print('Accessing the issue requires login.')
136 obj = rietveld.Rietveld(options.server, None, None)
137 try:
138 properties = obj.get_issue_properties(options.issue, False)
139 except rietveld.upload.ClientLoginError, e:
140 print('Accessing the issue requires proper credentials.')
141 return 1
142 171
143 if not options.patchset: 172 if not options.patchset:
144 options.patchset = properties['patchsets'][-1] 173 options.patchset = properties['patchsets'][-1]
145 print('No patchset specified. Using patchset %d' % options.patchset) 174 print('No patchset specified. Using patchset %d' % options.patchset)
146 175
147 print('Downloading the patch.') 176 print('Downloading the patch.')
148 try: 177 try:
149 patchset = obj.get_patch(options.issue, options.patchset) 178 patchset = obj.get_patch(options.issue, options.patchset)
150 except urllib2.HTTPError, e: 179 except urllib2.HTTPError, e:
151 print( 180 print(
(...skipping 64 matching lines...)
216 f, options.revision_mapping) 245 f, options.revision_mapping)
217 annotated_gclient.emit_buildprops(revisions) 246 annotated_gclient.emit_buildprops(revisions)
218 247
219 return retcode 248 return retcode
220 return 0 249 return 0
221 250
222 251
223 if __name__ == "__main__": 252 if __name__ == "__main__":
224 fix_encoding.fix_encoding() 253 fix_encoding.fix_encoding()
225 sys.exit(main()) 254 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | rietveld.py » ('j') | rietveld.py » ('J')

Powered by Google App Engine