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

Side by Side Diff: third_party/upload.py

Issue 14878007: Update update.py from rietveld/chromium@r1052. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 7 years, 7 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 | « no previous file | no next file » | 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 # coding: utf-8 2 # coding: utf-8
3 # 3 #
4 # Copyright 2007 Google Inc. 4 # Copyright 2007 Google Inc.
5 # 5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License. 7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at 8 # You may obtain a copy of the License at
9 # 9 #
10 # http://www.apache.org/licenses/LICENSE-2.0 10 # http://www.apache.org/licenses/LICENSE-2.0
(...skipping 16 matching lines...) Expand all
27 Subversion 27 Subversion
28 Perforce 28 Perforce
29 CVS 29 CVS
30 30
31 It is important for Git/Mercurial users to specify a tree/node/branch to diff 31 It is important for Git/Mercurial users to specify a tree/node/branch to diff
32 against by using the '--rev' option. 32 against by using the '--rev' option.
33 """ 33 """
34 # This code is derived from appcfg.py in the App Engine SDK (open source), 34 # This code is derived from appcfg.py in the App Engine SDK (open source),
35 # and from ASPN recipe #146306. 35 # and from ASPN recipe #146306.
36 36
37 import BaseHTTPServer
37 import ConfigParser 38 import ConfigParser
38 import cookielib 39 import cookielib
39 import errno 40 import errno
40 import fnmatch 41 import fnmatch
41 import getpass 42 import getpass
42 import logging 43 import logging
43 import marshal 44 import marshal
44 import mimetypes 45 import mimetypes
45 import optparse 46 import optparse
46 import os 47 import os
47 import re 48 import re
48 import socket 49 import socket
49 import subprocess 50 import subprocess
50 import sys 51 import sys
51 import urllib 52 import urllib
52 import urllib2 53 import urllib2
53 import urlparse 54 import urlparse
55 import webbrowser
54 56
55 # The md5 module was deprecated in Python 2.5. 57 # The md5 module was deprecated in Python 2.5.
56 try: 58 try:
57 from hashlib import md5 59 from hashlib import md5
58 except ImportError: 60 except ImportError:
59 from md5 import md5 61 from md5 import md5
60 62
61 try: 63 try:
62 import readline 64 import readline
63 except ImportError: 65 except ImportError:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 VCS_MERCURIAL.lower(): VCS_MERCURIAL, 101 VCS_MERCURIAL.lower(): VCS_MERCURIAL,
100 "hg": VCS_MERCURIAL, 102 "hg": VCS_MERCURIAL,
101 VCS_SUBVERSION.lower(): VCS_SUBVERSION, 103 VCS_SUBVERSION.lower(): VCS_SUBVERSION,
102 "svn": VCS_SUBVERSION, 104 "svn": VCS_SUBVERSION,
103 VCS_PERFORCE.lower(): VCS_PERFORCE, 105 VCS_PERFORCE.lower(): VCS_PERFORCE,
104 "p4": VCS_PERFORCE, 106 "p4": VCS_PERFORCE,
105 VCS_GIT.lower(): VCS_GIT, 107 VCS_GIT.lower(): VCS_GIT,
106 VCS_CVS.lower(): VCS_CVS, 108 VCS_CVS.lower(): VCS_CVS,
107 } 109 }
108 110
111 # OAuth 2.0-Related Constants
112 LOCALHOST_IP = '127.0.0.1'
113 DEFAULT_OAUTH2_PORT = 8001
114 ACCESS_TOKEN_PARAM = 'access_token'
115 OAUTH_PATH = '/get-access-token'
116 OAUTH_PATH_PORT_TEMPLATE = OAUTH_PATH + '?port=%(port)d'
117 AUTH_HANDLER_RESPONSE = """\
118 <html>
119 <head>
120 <title>Authentication Status</title>
121 </head>
122 <body>
123 <p>The authentication flow has completed.</p>
124 </body>
125 </html>
126 """
127 # Borrowed from google-api-python-client
128 OPEN_LOCAL_MESSAGE_TEMPLATE = """\
129 Your browser has been opened to visit:
130
131 %s
132
133 If your browser is on a different machine then exit and re-run
134 upload.py with the command-line parameter
135
136 --no_oauth2_webbrowser
137 """
138 NO_OPEN_LOCAL_MESSAGE_TEMPLATE = """\
139 Go to the following link in your browser:
140
141 %s
142
143 and copy the access token.
144 """
145
109 # The result of parsing Subversion's [auto-props] setting. 146 # The result of parsing Subversion's [auto-props] setting.
110 svn_auto_props_map = None 147 svn_auto_props_map = None
111 148
112 def GetEmail(prompt): 149 def GetEmail(prompt):
113 """Prompts the user for their email address and returns it. 150 """Prompts the user for their email address and returns it.
114 151
115 The last used email address is saved to a file and offered up as a suggestion 152 The last used email address is saved to a file and offered up as a suggestion
116 to the user. If the user presses enter without typing in anything the last 153 to the user. If the user presses enter without typing in anything the last
117 used email address is used. If the user enters a new address, it is saved 154 used email address is used. If the user enters a new address, it is saved
118 for next time we prompt. 155 for next time we prompt.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 def reason(self): 209 def reason(self):
173 # reason is a property on python 2.7 but a member variable on <=2.6. 210 # reason is a property on python 2.7 but a member variable on <=2.6.
174 # self.args is modified so it cannot be used as-is so save the value in 211 # self.args is modified so it cannot be used as-is so save the value in
175 # self._reason. 212 # self._reason.
176 return self._reason 213 return self._reason
177 214
178 215
179 class AbstractRpcServer(object): 216 class AbstractRpcServer(object):
180 """Provides a common interface for a simple RPC server.""" 217 """Provides a common interface for a simple RPC server."""
181 218
182 def __init__(self, host, auth_function, host_override=None, extra_headers={}, 219 def __init__(self, host, auth_function, host_override=None,
183 save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): 220 extra_headers=None, save_cookies=False,
221 account_type=AUTH_ACCOUNT_TYPE):
184 """Creates a new AbstractRpcServer. 222 """Creates a new AbstractRpcServer.
185 223
186 Args: 224 Args:
187 host: The host to send requests to. 225 host: The host to send requests to.
188 auth_function: A function that takes no arguments and returns an 226 auth_function: A function that takes no arguments and returns an
189 (email, password) tuple when called. Will be called if authentication 227 (email, password) tuple when called. Will be called if authentication
190 is required. 228 is required.
191 host_override: The host header to send to the server (defaults to host). 229 host_override: The host header to send to the server (defaults to host).
192 extra_headers: A dict of extra headers to append to every request. 230 extra_headers: A dict of extra headers to append to every request.
193 save_cookies: If True, save the authentication cookies to local disk. 231 save_cookies: If True, save the authentication cookies to local disk.
194 If False, use an in-memory cookiejar instead. Subclasses must 232 If False, use an in-memory cookiejar instead. Subclasses must
195 implement this functionality. Defaults to False. 233 implement this functionality. Defaults to False.
196 account_type: Account type used for authentication. Defaults to 234 account_type: Account type used for authentication. Defaults to
197 AUTH_ACCOUNT_TYPE. 235 AUTH_ACCOUNT_TYPE.
198 """ 236 """
199 self.host = host 237 self.host = host
200 if (not self.host.startswith("http://") and 238 if (not self.host.startswith("http://") and
201 not self.host.startswith("https://")): 239 not self.host.startswith("https://")):
202 self.host = "http://" + self.host 240 self.host = "http://" + self.host
203 self.host_override = host_override 241 self.host_override = host_override
204 self.auth_function = auth_function 242 self.auth_function = auth_function
205 self.authenticated = False 243 self.authenticated = False
206 self.extra_headers = extra_headers 244 self.extra_headers = extra_headers or {}
207 self.save_cookies = save_cookies 245 self.save_cookies = save_cookies
208 self.account_type = account_type 246 self.account_type = account_type
209 self.opener = self._GetOpener() 247 self.opener = self._GetOpener()
210 if self.host_override: 248 if self.host_override:
211 logging.info("Server: %s; Host: %s", self.host, self.host_override) 249 logging.info("Server: %s; Host: %s", self.host, self.host_override)
212 else: 250 else:
213 logging.info("Server: %s", self.host) 251 logging.info("Server: %s", self.host)
214 252
215 def _GetOpener(self): 253 def _GetOpener(self):
216 """Returns an OpenerDirector for making HTTP requests. 254 """Returns an OpenerDirector for making HTTP requests.
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 raise 456 raise
419 finally: 457 finally:
420 socket.setdefaulttimeout(old_timeout) 458 socket.setdefaulttimeout(old_timeout)
421 459
422 460
423 class HttpRpcServer(AbstractRpcServer): 461 class HttpRpcServer(AbstractRpcServer):
424 """Provides a simplified RPC-style interface for HTTP requests.""" 462 """Provides a simplified RPC-style interface for HTTP requests."""
425 463
426 def _Authenticate(self): 464 def _Authenticate(self):
427 """Save the cookie jar after authentication.""" 465 """Save the cookie jar after authentication."""
428 super(HttpRpcServer, self)._Authenticate() 466 if isinstance(self.auth_function, OAuth2Creds):
429 if self.save_cookies: 467 access_token = self.auth_function()
430 StatusUpdate("Saving authentication cookies to %s" % self.cookie_file) 468 if access_token is not None:
431 self.cookie_jar.save() 469 self.extra_headers['Authorization'] = 'OAuth %s' % (access_token,)
470 self.authenticated = True
471 else:
472 super(HttpRpcServer, self)._Authenticate()
473 if self.save_cookies:
474 StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
475 self.cookie_jar.save()
432 476
433 def _GetOpener(self): 477 def _GetOpener(self):
434 """Returns an OpenerDirector that supports cookies and ignores redirects. 478 """Returns an OpenerDirector that supports cookies and ignores redirects.
435 479
436 Returns: 480 Returns:
437 A urllib2.OpenerDirector object. 481 A urllib2.OpenerDirector object.
438 """ 482 """
439 opener = urllib2.OpenerDirector() 483 opener = urllib2.OpenerDirector()
440 opener.add_handler(urllib2.ProxyHandler()) 484 opener.add_handler(urllib2.ProxyHandler())
441 opener.add_handler(urllib2.UnknownHandler()) 485 opener.add_handler(urllib2.UnknownHandler())
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 optlist = optstr.split(", ") 532 optlist = optstr.split(", ")
489 if len(optlist) > 1: 533 if len(optlist) > 1:
490 if option.takes_value(): 534 if option.takes_value():
491 # strip METAVAR from all but the last option 535 # strip METAVAR from all but the last option
492 optlist = [x.split()[0] for x in optlist[:-1]] + optlist[-1:] 536 optlist = [x.split()[0] for x in optlist[:-1]] + optlist[-1:]
493 optstr = " ".join(optlist) 537 optstr = " ".join(optlist)
494 return optstr 538 return optstr
495 539
496 540
497 parser = optparse.OptionParser( 541 parser = optparse.OptionParser(
498 usage="%prog [options] [-- diff_options] [path...]", 542 usage=("%prog [options] [-- diff_options] [path...]\n"
543 "See also: http://code.google.com/p/rietveld/wiki/UploadPyUsage"),
499 add_help_option=False, 544 add_help_option=False,
500 formatter=CondensedHelpFormatter() 545 formatter=CondensedHelpFormatter()
501 ) 546 )
502 parser.add_option("-h", "--help", action="store_true", 547 parser.add_option("-h", "--help", action="store_true",
503 help="Show this help message and exit.") 548 help="Show this help message and exit.")
504 parser.add_option("-y", "--assume_yes", action="store_true", 549 parser.add_option("-y", "--assume_yes", action="store_true",
505 dest="assume_yes", default=False, 550 dest="assume_yes", default=False,
506 help="Assume that the answer to yes/no questions is 'yes'.") 551 help="Assume that the answer to yes/no questions is 'yes'.")
507 # Logging 552 # Logging
508 group = parser.add_option_group("Logging options") 553 group = parser.add_option_group("Logging options")
(...skipping 15 matching lines...) Expand all
524 "Defaults to '%default'.")) 569 "Defaults to '%default'."))
525 group.add_option("-e", "--email", action="store", dest="email", 570 group.add_option("-e", "--email", action="store", dest="email",
526 metavar="EMAIL", default=None, 571 metavar="EMAIL", default=None,
527 help="The username to use. Will prompt if omitted.") 572 help="The username to use. Will prompt if omitted.")
528 group.add_option("-H", "--host", action="store", dest="host", 573 group.add_option("-H", "--host", action="store", dest="host",
529 metavar="HOST", default=None, 574 metavar="HOST", default=None,
530 help="Overrides the Host header sent with all RPCs.") 575 help="Overrides the Host header sent with all RPCs.")
531 group.add_option("--no_cookies", action="store_false", 576 group.add_option("--no_cookies", action="store_false",
532 dest="save_cookies", default=True, 577 dest="save_cookies", default=True,
533 help="Do not save authentication cookies to local disk.") 578 help="Do not save authentication cookies to local disk.")
579 group.add_option("--oauth2", action="store_true",
580 dest="use_oauth2", default=False,
581 help="Use OAuth 2.0 instead of a password.")
582 group.add_option("--oauth2_port", action="store", type="int",
583 dest="oauth2_port", default=DEFAULT_OAUTH2_PORT,
584 help=("Port to use to handle OAuth 2.0 redirect. Must be an "
585 "integer in the range 1024-49151, defaults to "
586 "'%default'."))
587 group.add_option("--no_oauth2_webbrowser", action="store_false",
588 dest="open_oauth2_local_webbrowser", default=True,
589 help="Don't open a browser window to get an access token.")
534 group.add_option("--account_type", action="store", dest="account_type", 590 group.add_option("--account_type", action="store", dest="account_type",
535 metavar="TYPE", default=AUTH_ACCOUNT_TYPE, 591 metavar="TYPE", default=AUTH_ACCOUNT_TYPE,
536 choices=["GOOGLE", "HOSTED"], 592 choices=["GOOGLE", "HOSTED"],
537 help=("Override the default account type " 593 help=("Override the default account type "
538 "(defaults to '%default', " 594 "(defaults to '%default', "
539 "valid choices are 'GOOGLE' and 'HOSTED').")) 595 "valid choices are 'GOOGLE' and 'HOSTED')."))
540 # Issue 596 # Issue
541 group = parser.add_option_group("Issue options") 597 group = parser.add_option_group("Issue options")
542 group.add_option("-t", "--title", action="store", dest="title", 598 group.add_option("-t", "--title", action="store", dest="title",
543 help="New issue subject or new patch set title") 599 help="New issue subject or new patch set title")
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 metavar="P4_CHANGELIST", default=None, 661 metavar="P4_CHANGELIST", default=None,
606 help=("Perforce changelist id")) 662 help=("Perforce changelist id"))
607 group.add_option("--p4_client", action="store", dest="p4_client", 663 group.add_option("--p4_client", action="store", dest="p4_client",
608 metavar="P4_CLIENT", default=None, 664 metavar="P4_CLIENT", default=None,
609 help=("Perforce client/workspace")) 665 help=("Perforce client/workspace"))
610 group.add_option("--p4_user", action="store", dest="p4_user", 666 group.add_option("--p4_user", action="store", dest="p4_user",
611 metavar="P4_USER", default=None, 667 metavar="P4_USER", default=None,
612 help=("Perforce user")) 668 help=("Perforce user"))
613 669
614 670
671 # OAuth 2.0 Methods and Helpers
672 class ClientRedirectServer(BaseHTTPServer.HTTPServer):
673 """A server for redirects back to localhost from the associated server.
674
675 Waits for a single request and parses the query parameters for an access token
676 and then stops serving.
677 """
678 access_token = None
679
680
681 class ClientRedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler):
682 """A handler for redirects back to localhost from the associated server.
683
684 Waits for a single request and parses the query parameters into the server's
685 access_token and then stops serving.
686 """
687
688 def SetAccessToken(self):
689 """Stores the access token from the request on the server.
690
691 Will only do this if exactly one query parameter was passed in to the
692 request and that query parameter used 'access_token' as the key.
693 """
694 query_string = urlparse.urlparse(self.path).query
695 query_params = urlparse.parse_qs(query_string)
696
697 if len(query_params) == 1:
698 access_token_list = query_params.get(ACCESS_TOKEN_PARAM, [])
699 if len(access_token_list) == 1:
700 self.server.access_token = access_token_list[0]
701
702 def do_GET(self):
703 """Handle a GET request.
704
705 Parses and saves the query parameters and prints a message that the server
706 has completed its lone task (handling a redirect).
707
708 Note that we can't detect if an error occurred.
709 """
710 self.send_response(200)
711 self.send_header('Content-type', 'text/html')
712 self.end_headers()
713 self.SetAccessToken()
714 self.wfile.write(AUTH_HANDLER_RESPONSE)
715
716 def log_message(self, format, *args):
717 """Do not log messages to stdout while running as command line program."""
718 pass
719
720
721 def OpenOAuth2ConsentPage(server=DEFAULT_REVIEW_SERVER,
722 port=DEFAULT_OAUTH2_PORT):
723 """Opens the OAuth 2.0 consent page or prints instructions how to.
724
725 Uses the webbrowser module to open the OAuth server side page in a browser.
726
727 Args:
728 server: String containing the review server URL. Defaults to
729 DEFAULT_REVIEW_SERVER.
730 port: Integer, the port where the localhost server receiving the redirect
731 is serving. Defaults to DEFAULT_OAUTH2_PORT.
732 """
733 path = OAUTH_PATH_PORT_TEMPLATE % {'port': port}
734 page = 'https://%s%s' % (server, path)
735 webbrowser.open(page, new=1, autoraise=True)
736 print OPEN_LOCAL_MESSAGE_TEMPLATE % (page,)
737
738
739 def WaitForAccessToken(port=DEFAULT_OAUTH2_PORT):
740 """Spins up a simple HTTP Server to handle a single request.
741
742 Intended to handle a single redirect from the production server after the
743 user authenticated via OAuth 2.0 with the server.
744
745 Args:
746 port: Integer, the port where the localhost server receiving the redirect
747 is serving. Defaults to DEFAULT_OAUTH2_PORT.
748
749 Returns:
750 The access token passed to the localhost server, or None if no access token
751 was passed.
752 """
753 httpd = ClientRedirectServer((LOCALHOST_IP, port), ClientRedirectHandler)
754 # Wait to serve just one request before deferring control back
755 # to the caller of wait_for_refresh_token
756 httpd.handle_request()
757 return httpd.access_token
758
759
760 def GetAccessToken(server=DEFAULT_REVIEW_SERVER, port=DEFAULT_OAUTH2_PORT,
761 open_local_webbrowser=True):
762 """Gets an Access Token for the current user.
763
764 Args:
765 server: String containing the review server URL. Defaults to
766 DEFAULT_REVIEW_SERVER.
767 port: Integer, the port where the localhost server receiving the redirect
768 is serving. Defaults to DEFAULT_OAUTH2_PORT.
769 open_local_webbrowser: Boolean, defaults to True. If set, opens a page in
770 the user's browser.
771
772 Returns:
773 A string access token that was sent to the local server. If the serving page
774 via WaitForAccessToken does not receive an access token, this method
775 returns None.
776 """
777 access_token = None
778 if open_local_webbrowser:
779 OpenOAuth2ConsentPage(server=server, port=port)
780 try:
781 access_token = WaitForAccessToken(port=port)
782 except socket.error, e:
783 print 'Can\'t start local webserver. Socket Error: %s\n' % (e.strerror,)
784
785 if access_token is None:
786 # TODO(dhermes): Offer to add to clipboard using xsel, xclip, pbcopy, etc.
787 page = 'https://%s%s' % (server, OAUTH_PATH)
788 print NO_OPEN_LOCAL_MESSAGE_TEMPLATE % (page,)
789 access_token = raw_input('Enter access token: ').strip()
790
791 return access_token
792
793
615 class KeyringCreds(object): 794 class KeyringCreds(object):
616 def __init__(self, server, host, email): 795 def __init__(self, server, host, email):
617 self.server = server 796 self.server = server
618 self.host = host 797 # Explicitly cast host to str to work around bug in old versions of Keyring
798 # (versions before 0.10). Even though newer versions of Keyring fix this,
799 # some modern linuxes (such as Ubuntu 12.04) still bundle a version with
800 # the bug.
801 self.host = str(host)
619 self.email = email 802 self.email = email
620 self.accounts_seen = set() 803 self.accounts_seen = set()
621 804
622 def GetUserCredentials(self): 805 def GetUserCredentials(self):
623 """Prompts the user for a username and password. 806 """Prompts the user for a username and password.
624 807
625 Only use keyring on the initial call. If the keyring contains the wrong 808 Only use keyring on the initial call. If the keyring contains the wrong
626 password, we want to give the user a chance to enter another one. 809 password, we want to give the user a chance to enter another one.
627 """ 810 """
628 # Create a local alias to the email variable to avoid Python's crazy 811 # Create a local alias to the email variable to avoid Python's crazy
(...skipping 17 matching lines...) Expand all
646 else: 829 else:
647 password = getpass.getpass("Password for %s: " % email) 830 password = getpass.getpass("Password for %s: " % email)
648 if keyring: 831 if keyring:
649 answer = raw_input("Store password in system keyring?(y/N) ").strip() 832 answer = raw_input("Store password in system keyring?(y/N) ").strip()
650 if answer == "y": 833 if answer == "y":
651 keyring.set_password(self.host, email, password) 834 keyring.set_password(self.host, email, password)
652 self.accounts_seen.add(email) 835 self.accounts_seen.add(email)
653 return (email, password) 836 return (email, password)
654 837
655 838
839 class OAuth2Creds(object):
840 """Simple object to hold server and port to be passed to GetAccessToken."""
841
842 def __init__(self, server, port, open_local_webbrowser=True):
843 self.server = server
844 self.port = port
845 self.open_local_webbrowser = open_local_webbrowser
846
847 def __call__(self):
848 """Uses stored server and port to retrieve OAuth 2.0 access token."""
849 return GetAccessToken(server=self.server, port=self.port,
850 open_local_webbrowser=self.open_local_webbrowser)
851
852
656 def GetRpcServer(server, email=None, host_override=None, save_cookies=True, 853 def GetRpcServer(server, email=None, host_override=None, save_cookies=True,
657 account_type=AUTH_ACCOUNT_TYPE): 854 account_type=AUTH_ACCOUNT_TYPE, use_oauth2=False,
855 oauth2_port=DEFAULT_OAUTH2_PORT,
856 open_oauth2_local_webbrowser=True):
658 """Returns an instance of an AbstractRpcServer. 857 """Returns an instance of an AbstractRpcServer.
659 858
660 Args: 859 Args:
661 server: String containing the review server URL. 860 server: String containing the review server URL.
662 email: String containing user's email address. 861 email: String containing user's email address.
663 host_override: If not None, string containing an alternate hostname to use 862 host_override: If not None, string containing an alternate hostname to use
664 in the host header. 863 in the host header.
665 save_cookies: Whether authentication cookies should be saved to disk. 864 save_cookies: Whether authentication cookies should be saved to disk.
666 account_type: Account type for authentication, either 'GOOGLE' 865 account_type: Account type for authentication, either 'GOOGLE'
667 or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE. 866 or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE.
867 use_oauth2: Boolean indicating whether OAuth 2.0 should be used for
868 authentication.
869 oauth2_port: Integer, the port where the localhost server receiving the
870 redirect is serving. Defaults to DEFAULT_OAUTH2_PORT.
871 open_oauth2_local_webbrowser: Boolean, defaults to True. If True and using
872 OAuth, this opens a page in the user's browser to obtain a token.
668 873
669 Returns: 874 Returns:
670 A new HttpRpcServer, on which RPC calls can be made. 875 A new HttpRpcServer, on which RPC calls can be made.
671 """ 876 """
672
673 # If this is the dev_appserver, use fake authentication. 877 # If this is the dev_appserver, use fake authentication.
674 host = (host_override or server).lower() 878 host = (host_override or server).lower()
675 if re.match(r'(http://)?localhost([:/]|$)', host): 879 if re.match(r'(http://)?localhost([:/]|$)', host):
676 if email is None: 880 if email is None:
677 email = "test@example.com" 881 email = "test@example.com"
678 logging.info("Using debug user %s. Override with --email" % email) 882 logging.info("Using debug user %s. Override with --email" % email)
679 server = HttpRpcServer( 883 server = HttpRpcServer(
680 server, 884 server,
681 lambda: (email, "password"), 885 lambda: (email, "password"),
682 host_override=host_override, 886 host_override=host_override,
683 extra_headers={"Cookie": 887 extra_headers={"Cookie":
684 'dev_appserver_login="%s:False"' % email}, 888 'dev_appserver_login="%s:False"' % email},
685 save_cookies=save_cookies, 889 save_cookies=save_cookies,
686 account_type=account_type) 890 account_type=account_type)
687 # Don't try to talk to ClientLogin. 891 # Don't try to talk to ClientLogin.
688 server.authenticated = True 892 server.authenticated = True
689 return server 893 return server
690 894
691 return HttpRpcServer(server, 895 positional_args = [server]
692 KeyringCreds(server, host, email).GetUserCredentials, 896 if use_oauth2:
897 positional_args.append(
898 OAuth2Creds(server, oauth2_port, open_oauth2_local_webbrowser))
899 else:
900 positional_args.append(KeyringCreds(server, host, email).GetUserCredentials)
901 return HttpRpcServer(*positional_args,
693 host_override=host_override, 902 host_override=host_override,
694 save_cookies=save_cookies) 903 save_cookies=save_cookies,
904 account_type=account_type)
695 905
696 906
697 def EncodeMultipartFormData(fields, files): 907 def EncodeMultipartFormData(fields, files):
698 """Encode form fields for multipart/form-data. 908 """Encode form fields for multipart/form-data.
699 909
700 Args: 910 Args:
701 fields: A sequence of (name, value) elements for regular form fields. 911 fields: A sequence of (name, value) elements for regular form fields.
702 files: A sequence of (name, filename, value) elements for data to be 912 files: A sequence of (name, filename, value) elements for data to be
703 uploaded as files. 913 uploaded as files.
704 Returns: 914 Returns:
(...skipping 1497 matching lines...) Expand 10 before | Expand all | Expand 10 after
2202 2412
2203 Returns: 2413 Returns:
2204 A 2-tuple (issue id, patchset id). 2414 A 2-tuple (issue id, patchset id).
2205 The patchset id is None if the base files are not uploaded by this 2415 The patchset id is None if the base files are not uploaded by this
2206 script (applies only to SVN checkouts). 2416 script (applies only to SVN checkouts).
2207 """ 2417 """
2208 options, args = parser.parse_args(argv[1:]) 2418 options, args = parser.parse_args(argv[1:])
2209 if options.help: 2419 if options.help:
2210 if options.verbose < 2: 2420 if options.verbose < 2:
2211 # hide Perforce options 2421 # hide Perforce options
2212 parser.epilog = "Use '--help -v' to show additional Perforce options." 2422 parser.epilog = (
2423 "Use '--help -v' to show additional Perforce options. "
2424 "For more help, see "
2425 "http://code.google.com/p/rietveld/wiki/CodeReviewHelp"
2426 )
2213 parser.option_groups.remove(parser.get_option_group('--p4_port')) 2427 parser.option_groups.remove(parser.get_option_group('--p4_port'))
2214 parser.print_help() 2428 parser.print_help()
2215 sys.exit(0) 2429 sys.exit(0)
2216 2430
2217 global verbosity 2431 global verbosity
2218 verbosity = options.verbose 2432 verbosity = options.verbose
2219 if verbosity >= 3: 2433 if verbosity >= 3:
2220 logging.getLogger().setLevel(logging.DEBUG) 2434 logging.getLogger().setLevel(logging.DEBUG)
2221 elif verbosity >= 2: 2435 elif verbosity >= 2:
2222 logging.getLogger().setLevel(logging.INFO) 2436 logging.getLogger().setLevel(logging.INFO)
(...skipping 20 matching lines...) Expand all
2243 if data is None: 2457 if data is None:
2244 data = vcs.GenerateDiff(args) 2458 data = vcs.GenerateDiff(args)
2245 data = vcs.PostProcessDiff(data) 2459 data = vcs.PostProcessDiff(data)
2246 if options.print_diffs: 2460 if options.print_diffs:
2247 print "Rietveld diff start:*****" 2461 print "Rietveld diff start:*****"
2248 print data 2462 print data
2249 print "Rietveld diff end:*****" 2463 print "Rietveld diff end:*****"
2250 files = vcs.GetBaseFiles(data) 2464 files = vcs.GetBaseFiles(data)
2251 if verbosity >= 1: 2465 if verbosity >= 1:
2252 print "Upload server:", options.server, "(change with -s/--server)" 2466 print "Upload server:", options.server, "(change with -s/--server)"
2467 if options.use_oauth2:
2468 options.save_cookies = False
2253 rpc_server = GetRpcServer(options.server, 2469 rpc_server = GetRpcServer(options.server,
2254 options.email, 2470 options.email,
2255 options.host, 2471 options.host,
2256 options.save_cookies, 2472 options.save_cookies,
2257 options.account_type) 2473 options.account_type,
2474 options.use_oauth2,
2475 options.oauth2_port,
2476 options.open_oauth2_local_webbrowser)
2258 form_fields = [] 2477 form_fields = []
2259 2478
2260 repo_guid = vcs.GetGUID() 2479 repo_guid = vcs.GetGUID()
2261 if repo_guid: 2480 if repo_guid:
2262 form_fields.append(("repo_guid", repo_guid)) 2481 form_fields.append(("repo_guid", repo_guid))
2263 if base: 2482 if base:
2264 b = urlparse.urlparse(base) 2483 b = urlparse.urlparse(base)
2265 username, netloc = urllib.splituser(b.netloc) 2484 username, netloc = urllib.splituser(b.netloc)
2266 if username: 2485 if username:
2267 logging.info("Removed username from base URL") 2486 logging.info("Removed username from base URL")
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 os.environ['LC_ALL'] = 'C' 2603 os.environ['LC_ALL'] = 'C'
2385 RealMain(sys.argv) 2604 RealMain(sys.argv)
2386 except KeyboardInterrupt: 2605 except KeyboardInterrupt:
2387 print 2606 print
2388 StatusUpdate("Interrupted.") 2607 StatusUpdate("Interrupted.")
2389 sys.exit(1) 2608 sys.exit(1)
2390 2609
2391 2610
2392 if __name__ == "__main__": 2611 if __name__ == "__main__":
2393 main() 2612 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698