OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2007 Google Inc. | 3 # Copyright 2007 Google Inc. |
4 # | 4 # |
5 # Licensed under the Apache License, Version 2.0 (the "License"); | 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
6 # you may not use this file except in compliance with the License. | 6 # you may not use this file except in compliance with the License. |
7 # You may obtain a copy of the License at | 7 # You may obtain a copy of the License at |
8 # | 8 # |
9 # http://www.apache.org/licenses/LICENSE-2.0 | 9 # http://www.apache.org/licenses/LICENSE-2.0 |
10 # | 10 # |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 sys.exit(1) | 164 sys.exit(1) |
165 | 165 |
166 | 166 |
167 class ClientLoginError(urllib2.HTTPError): | 167 class ClientLoginError(urllib2.HTTPError): |
168 """Raised to indicate there was an error authenticating with ClientLogin.""" | 168 """Raised to indicate there was an error authenticating with ClientLogin.""" |
169 | 169 |
170 def __init__(self, url, code, msg, headers, args): | 170 def __init__(self, url, code, msg, headers, args): |
171 urllib2.HTTPError.__init__(self, url, code, msg, headers, None) | 171 urllib2.HTTPError.__init__(self, url, code, msg, headers, None) |
172 self.args = args | 172 self.args = args |
173 self.reason = args["Error"] | 173 self.reason = args["Error"] |
| 174 self.info = args.get("Info", None) |
174 | 175 |
175 | 176 |
176 class AbstractRpcServer(object): | 177 class AbstractRpcServer(object): |
177 """Provides a common interface for a simple RPC server.""" | 178 """Provides a common interface for a simple RPC server.""" |
178 | 179 |
179 def __init__(self, host, auth_function, host_override=None, extra_headers={}, | 180 def __init__(self, host, auth_function, host_override=None, extra_headers={}, |
180 save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): | 181 save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): |
181 """Creates a new HttpRpcServer. | 182 """Creates a new HttpRpcServer. |
182 | 183 |
183 Args: | 184 Args: |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 | 308 |
308 If we attempt to access the upload API without first obtaining an | 309 If we attempt to access the upload API without first obtaining an |
309 authentication cookie, it returns a 401 response (or a 302) and | 310 authentication cookie, it returns a 401 response (or a 302) and |
310 directs us to authenticate ourselves with ClientLogin. | 311 directs us to authenticate ourselves with ClientLogin. |
311 """ | 312 """ |
312 for i in range(3): | 313 for i in range(3): |
313 credentials = self.auth_function() | 314 credentials = self.auth_function() |
314 try: | 315 try: |
315 auth_token = self._GetAuthToken(credentials[0], credentials[1]) | 316 auth_token = self._GetAuthToken(credentials[0], credentials[1]) |
316 except ClientLoginError, e: | 317 except ClientLoginError, e: |
| 318 print >>sys.stderr, '' |
317 if e.reason == "BadAuthentication": | 319 if e.reason == "BadAuthentication": |
318 print >>sys.stderr, "Invalid username or password." | 320 if e.info == "InvalidSecondFactor": |
319 continue | 321 print >>sys.stderr, ( |
320 if e.reason == "CaptchaRequired": | 322 "Use an application-specific password instead " |
| 323 "of your regular account password.\n" |
| 324 "See http://www.google.com/" |
| 325 "support/accounts/bin/answer.py?answer=185833") |
| 326 else: |
| 327 print >>sys.stderr, "Invalid username or password." |
| 328 elif e.reason == "CaptchaRequired": |
321 print >>sys.stderr, ( | 329 print >>sys.stderr, ( |
322 "Please go to\n" | 330 "Please go to\n" |
323 "https://www.google.com/accounts/DisplayUnlockCaptcha\n" | 331 "https://www.google.com/accounts/DisplayUnlockCaptcha\n" |
324 "and verify you are a human. Then try again.\n" | 332 "and verify you are a human. Then try again.\n" |
325 "If you are using a Google Apps account the URL is:\n" | 333 "If you are using a Google Apps account the URL is:\n" |
326 "https://www.google.com/a/yourdomain.com/UnlockCaptcha") | 334 "https://www.google.com/a/yourdomain.com/UnlockCaptcha") |
327 break | 335 elif e.reason == "NotVerified": |
328 if e.reason == "NotVerified": | |
329 print >>sys.stderr, "Account not verified." | 336 print >>sys.stderr, "Account not verified." |
330 break | 337 elif e.reason == "TermsNotAgreed": |
331 if e.reason == "TermsNotAgreed": | |
332 print >>sys.stderr, "User has not agreed to TOS." | 338 print >>sys.stderr, "User has not agreed to TOS." |
333 break | 339 elif e.reason == "AccountDeleted": |
334 if e.reason == "AccountDeleted": | |
335 print >>sys.stderr, "The user account has been deleted." | 340 print >>sys.stderr, "The user account has been deleted." |
336 break | 341 elif e.reason == "AccountDisabled": |
337 if e.reason == "AccountDisabled": | |
338 print >>sys.stderr, "The user account has been disabled." | 342 print >>sys.stderr, "The user account has been disabled." |
339 break | 343 break |
340 if e.reason == "ServiceDisabled": | 344 elif e.reason == "ServiceDisabled": |
341 print >>sys.stderr, ("The user's access to the service has been " | 345 print >>sys.stderr, ("The user's access to the service has been " |
342 "disabled.") | 346 "disabled.") |
343 break | 347 elif e.reason == "ServiceUnavailable": |
344 if e.reason == "ServiceUnavailable": | |
345 print >>sys.stderr, "The service is not available; try again later." | 348 print >>sys.stderr, "The service is not available; try again later." |
346 break | 349 else: |
347 raise | 350 # Unknown error. |
| 351 raise |
| 352 print >>sys.stderr, '' |
| 353 continue |
348 self._GetAuthCookie(auth_token) | 354 self._GetAuthCookie(auth_token) |
349 return | 355 return |
350 | 356 |
351 def Send(self, request_path, payload=None, | 357 def Send(self, request_path, payload=None, |
352 content_type="application/octet-stream", | 358 content_type="application/octet-stream", |
353 timeout=None, | 359 timeout=None, |
354 extra_headers=None, | 360 extra_headers=None, |
355 **kwargs): | 361 **kwargs): |
356 """Sends an RPC and returns the response. | 362 """Sends an RPC and returns the response. |
357 | 363 |
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 return (base_content, new_content, is_binary, status) | 1337 return (base_content, new_content, is_binary, status) |
1332 | 1338 |
1333 def GenerateDiff(self, extra_args): | 1339 def GenerateDiff(self, extra_args): |
1334 cmd = ["cvs", "diff", "-u", "-N"] | 1340 cmd = ["cvs", "diff", "-u", "-N"] |
1335 if self.options.revision: | 1341 if self.options.revision: |
1336 cmd += ["-r", self.options.revision] | 1342 cmd += ["-r", self.options.revision] |
1337 | 1343 |
1338 cmd.extend(extra_args) | 1344 cmd.extend(extra_args) |
1339 data, retcode = RunShellWithReturnCode(cmd) | 1345 data, retcode = RunShellWithReturnCode(cmd) |
1340 count = 0 | 1346 count = 0 |
1341 if retcode == 0: | 1347 if retcode in [0, 1]: |
1342 for line in data.splitlines(): | 1348 for line in data.splitlines(): |
1343 if line.startswith("Index:"): | 1349 if line.startswith("Index:"): |
1344 count += 1 | 1350 count += 1 |
1345 logging.info(line) | 1351 logging.info(line) |
1346 | 1352 |
1347 if not count: | 1353 if not count: |
1348 ErrorExit("No valid patches found in output from cvs diff") | 1354 ErrorExit("No valid patches found in output from cvs diff") |
1349 | 1355 |
1350 return data | 1356 return data |
1351 | 1357 |
1352 def GetUnknownFiles(self): | 1358 def GetUnknownFiles(self): |
1353 status = RunShell(["cvs", "diff"], | 1359 data, retcode = RunShellWithReturnCode(["cvs", "diff"]) |
1354 silent_ok=True) | 1360 if retcode not in [0, 1]: |
| 1361 ErrorExit("Got error status from 'cvs diff':\n%s" % (data,)) |
1355 unknown_files = [] | 1362 unknown_files = [] |
1356 for line in status.split("\n"): | 1363 for line in data.split("\n"): |
1357 if line and line[0] == "?": | 1364 if line and line[0] == "?": |
1358 unknown_files.append(line) | 1365 unknown_files.append(line) |
1359 return unknown_files | 1366 return unknown_files |
1360 | 1367 |
1361 class MercurialVCS(VersionControlSystem): | 1368 class MercurialVCS(VersionControlSystem): |
1362 """Implementation of the VersionControlSystem interface for Mercurial.""" | 1369 """Implementation of the VersionControlSystem interface for Mercurial.""" |
1363 | 1370 |
1364 def __init__(self, options, repo_dir): | 1371 def __init__(self, options, repo_dir): |
1365 super(MercurialVCS, self).__init__(options) | 1372 super(MercurialVCS, self).__init__(options) |
1366 # Absolute path to repository (we can be in a subdir) | 1373 # Absolute path to repository (we can be in a subdir) |
(...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2230 os.environ['LC_ALL'] = 'C' | 2237 os.environ['LC_ALL'] = 'C' |
2231 RealMain(sys.argv) | 2238 RealMain(sys.argv) |
2232 except KeyboardInterrupt: | 2239 except KeyboardInterrupt: |
2233 print | 2240 print |
2234 StatusUpdate("Interrupted.") | 2241 StatusUpdate("Interrupted.") |
2235 sys.exit(1) | 2242 sys.exit(1) |
2236 | 2243 |
2237 | 2244 |
2238 if __name__ == "__main__": | 2245 if __name__ == "__main__": |
2239 main() | 2246 main() |
OLD | NEW |