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

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: openssl package is now optional (correct patch) Created 6 years, 9 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 | rietveld.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
(...skipping 23 matching lines...) Expand all
34 34
35 def write(self, data): 35 def write(self, data):
36 self.stream.write(data) 36 self.stream.write(data)
37 self.stream.flush() 37 self.stream.flush()
38 38
39 def __getattr__(self, attr): 39 def __getattr__(self, attr):
40 return getattr(self.stream, attr) 40 return getattr(self.stream, attr)
41 41
42 42
43 def main(): 43 def main():
44 # TODO(pgervais): This function is way too long. Split.
44 sys.stdout = Unbuffered(sys.stdout) 45 sys.stdout = Unbuffered(sys.stdout)
45 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) 46 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
46 parser.add_option( 47 parser.add_option(
47 '-v', '--verbose', action='count', default=0, 48 '-v', '--verbose', action='count', default=0,
48 help='Prints debugging infos') 49 help='Prints debugging infos')
49 parser.add_option( 50 parser.add_option(
50 '-e', '--email', 51 '-e', '--email',
51 help='Email address to access rietveld. If not specified, anonymous ' 52 help='Email address to access rietveld. If not specified, anonymous '
52 'access will be used.') 53 'access will be used.')
53 parser.add_option( 54 parser.add_option(
54 '-w', '--password', default=None, 55 '-E', '--email-file',
55 help='Password for email addressed. Use - to read password from stdin.') 56 help='File containing the email address to access rietveld. '
57 'If not specified, anonymous access will be used.')
58 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',
64 help='Path to file containing a private key in p12 format for OAuth2 '
65 'authentication. Use -w to provide the decrypting password, if any.')
56 parser.add_option( 66 parser.add_option(
57 '-i', '--issue', type='int', help='Rietveld issue number') 67 '-i', '--issue', type='int', help='Rietveld issue number')
58 parser.add_option( 68 parser.add_option(
59 '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number') 69 '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number')
60 parser.add_option( 70 parser.add_option(
61 '-r', 71 '-r',
62 '--root_dir', 72 '--root_dir',
63 default=os.getcwd(), 73 default=os.getcwd(),
64 help='Root directory to apply the patch') 74 help='Root directory to apply the patch')
65 parser.add_option( 75 parser.add_option(
66 '-s', 76 '-s',
67 '--server', 77 '--server',
68 default='http://codereview.chromium.org', 78 default='http://codereview.chromium.org',
69 help='Rietveld server') 79 help='Rietveld server')
70 parser.add_option('--no-auth', action='store_true', 80 parser.add_option('--no-auth', action='store_true',
71 help='Do not attempt authenticated requests.') 81 help='Do not attempt authenticated requests.')
72 parser.add_option('--revision-mapping', default='{}', 82 parser.add_option('--revision-mapping', default='{}',
73 help='When running gclient, annotate the got_revisions ' 83 help='When running gclient, annotate the got_revisions '
74 'using the revision-mapping.') 84 'using the revision-mapping.')
75 parser.add_option('-f', '--force', action='store_true', 85 parser.add_option('-f', '--force', action='store_true',
76 help='Really run apply_issue, even if .update.flag ' 86 help='Really run apply_issue, even if .update.flag '
77 'is detected.') 87 'is detected.')
78 parser.add_option('-b', '--base_ref', help='Base git ref to patch on top of, ' 88 parser.add_option('-b', '--base_ref', help='Base git ref to patch on top of, '
79 'used for verification.') 89 'used for verification.')
80 options, args = parser.parse_args() 90 options, args = parser.parse_args()
91
92 if options.password and options.private_key_file:
93 parser.error('-k and -w options are incompatible')
94 if options.email and options.email_file:
95 parser.error('-e and -E options are incompatible')
96
81 if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag')) 97 if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag'))
82 and not options.force): 98 and not options.force):
83 print 'update.flag file found: bot_update has run and checkout is already ' 99 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.' 100 print 'in a consistent state. No actions will be performed in this step.'
85 return 0 101 return 0
86 logging.basicConfig( 102 logging.basicConfig(
87 format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s', 103 format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s',
88 level=[logging.WARNING, logging.INFO, logging.DEBUG][ 104 level=[logging.WARNING, logging.INFO, logging.DEBUG][
89 min(2, options.verbose)]) 105 min(2, options.verbose)])
90 if args: 106 if args:
91 parser.error('Extra argument(s) "%s" not understood' % ' '.join(args)) 107 parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))
92 if not options.issue: 108 if not options.issue:
93 parser.error('Require --issue') 109 parser.error('Require --issue')
94 options.server = options.server.rstrip('/') 110 options.server = options.server.rstrip('/')
95 if not options.server: 111 if not options.server:
96 parser.error('Require a valid server') 112 parser.error('Require a valid server')
97 113
98 options.revision_mapping = json.loads(options.revision_mapping) 114 options.revision_mapping = json.loads(options.revision_mapping)
99 115
100 if options.password == '-': 116 if options.password == '-':
101 print('Reading password') 117 print('Reading password')
102 options.password = sys.stdin.readline().strip() 118 options.password = sys.stdin.readline().strip()
103 119
120 # read email if needed
121 if options.email_file:
122 if not os.path.exists(options.email_file):
123 parser.error('file does not exist: %s' % options.email_file)
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.JwtOAuth2Rietveld(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 as e:
124 pass 145 if e.getcode() != 302:
125 if properties is None: 146 raise
126 if options.email is not None: 147 if 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...) Expand 10 before | Expand all | Expand 10 after
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') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698