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

Side by Side Diff: third_party/upload.py

Issue 10907089: Update upload.py from upstream at 40853b0f868a. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Update @ d5f7dffc2dbb Created 8 years, 3 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 """Raised to indicate there was an error authenticating with ClientLogin.""" 163 """Raised to indicate there was an error authenticating with ClientLogin."""
164 164
165 def __init__(self, url, code, msg, headers, args): 165 def __init__(self, url, code, msg, headers, args):
166 urllib2.HTTPError.__init__(self, url, code, msg, headers, None) 166 urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
167 self.args = args 167 self.args = args
168 self._reason = args["Error"] 168 self._reason = args["Error"]
169 self.info = args.get("Info", None) 169 self.info = args.get("Info", None)
170 170
171 @property 171 @property
172 def reason(self): 172 def reason(self):
173 # 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
175 # self._reason.
173 return self._reason 176 return self._reason
174 177
175 178
176 class AbstractRpcServer(object): 179 class AbstractRpcServer(object):
177 """Provides a common interface for a simple RPC server.""" 180 """Provides a common interface for a simple RPC server."""
178 181
179 def __init__(self, host, auth_function, host_override=None, extra_headers={}, 182 def __init__(self, host, auth_function, host_override=None, extra_headers={},
180 save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): 183 save_cookies=False, account_type=AUTH_ACCOUNT_TYPE):
181 """Creates a new HttpRpcServer. 184 """Creates a new AbstractRpcServer.
182 185
183 Args: 186 Args:
184 host: The host to send requests to. 187 host: The host to send requests to.
185 auth_function: A function that takes no arguments and returns an 188 auth_function: A function that takes no arguments and returns an
186 (email, password) tuple when called. Will be called if authentication 189 (email, password) tuple when called. Will be called if authentication
187 is required. 190 is required.
188 host_override: The host header to send to the server (defaults to host). 191 host_override: The host header to send to the server (defaults to host).
189 extra_headers: A dict of extra headers to append to every request. 192 extra_headers: A dict of extra headers to append to every request.
190 save_cookies: If True, save the authentication cookies to local disk. 193 save_cookies: If True, save the authentication cookies to local disk.
191 If False, use an in-memory cookiejar instead. Subclasses must 194 If False, use an in-memory cookiejar instead. Subclasses must
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 group.add_option("--p4_changelist", action="store", dest="p4_changelist", 595 group.add_option("--p4_changelist", action="store", dest="p4_changelist",
593 metavar="P4_CHANGELIST", default=None, 596 metavar="P4_CHANGELIST", default=None,
594 help=("Perforce changelist id")) 597 help=("Perforce changelist id"))
595 group.add_option("--p4_client", action="store", dest="p4_client", 598 group.add_option("--p4_client", action="store", dest="p4_client",
596 metavar="P4_CLIENT", default=None, 599 metavar="P4_CLIENT", default=None,
597 help=("Perforce client/workspace")) 600 help=("Perforce client/workspace"))
598 group.add_option("--p4_user", action="store", dest="p4_user", 601 group.add_option("--p4_user", action="store", dest="p4_user",
599 metavar="P4_USER", default=None, 602 metavar="P4_USER", default=None,
600 help=("Perforce user")) 603 help=("Perforce user"))
601 604
605
606 class KeyringCreds(object):
607 def __init__(self, server, host, email):
608 self.server = server
609 self.host = host
610 self.email = email
611 self.accounts_seen = set()
612
613 def GetUserCredentials(self):
614 """Prompts the user for a username and password.
615
616 Only use keyring on the initial call. If the keyring contains the wrong
617 password, we want to give the user a chance to enter another one.
618 """
619 # Create a local alias to the email variable to avoid Python's crazy
620 # scoping rules.
621 global keyring
622 email = self.email
623 if email is None:
624 email = GetEmail("Email (login for uploading to %s)" % self.server)
625 password = None
626 if keyring and not email in self.accounts_seen:
627 try:
628 password = keyring.get_password(self.host, email)
629 except:
630 # Sadly, we have to trap all errors here as
631 # gnomekeyring.IOError inherits from object. :/
632 print "Failed to get password from keyring"
633 keyring = None
634 if password is not None:
635 print "Using password from system keyring."
636 self.accounts_seen.add(email)
637 else:
638 password = getpass.getpass("Password for %s: " % email)
639 if keyring:
640 answer = raw_input("Store password in system keyring?(y/N) ").strip()
641 if answer == "y":
642 keyring.set_password(host, email, password)
643 self.accounts_seen.add(email)
644 return (email, password)
645
646
602 def GetRpcServer(server, email=None, host_override=None, save_cookies=True, 647 def GetRpcServer(server, email=None, host_override=None, save_cookies=True,
603 account_type=AUTH_ACCOUNT_TYPE): 648 account_type=AUTH_ACCOUNT_TYPE):
604 """Returns an instance of an AbstractRpcServer. 649 """Returns an instance of an AbstractRpcServer.
605 650
606 Args: 651 Args:
607 server: String containing the review server URL. 652 server: String containing the review server URL.
608 email: String containing user's email address. 653 email: String containing user's email address.
609 host_override: If not None, string containing an alternate hostname to use 654 host_override: If not None, string containing an alternate hostname to use
610 in the host header. 655 in the host header.
611 save_cookies: Whether authentication cookies should be saved to disk. 656 save_cookies: Whether authentication cookies should be saved to disk.
612 account_type: Account type for authentication, either 'GOOGLE' 657 account_type: Account type for authentication, either 'GOOGLE'
613 or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE. 658 or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE.
614 659
615 Returns: 660 Returns:
616 A new AbstractRpcServer, on which RPC calls can be made. 661 A new HttpRpcServer, on which RPC calls can be made.
617 """ 662 """
618 663
619 rpc_server_class = HttpRpcServer
620
621 # If this is the dev_appserver, use fake authentication. 664 # If this is the dev_appserver, use fake authentication.
622 host = (host_override or server).lower() 665 host = (host_override or server).lower()
623 if re.match(r'(http://)?localhost([:/]|$)', host): 666 if re.match(r'(http://)?localhost([:/]|$)', host):
624 if email is None: 667 if email is None:
625 email = "test@example.com" 668 email = "test@example.com"
626 logging.info("Using debug user %s. Override with --email" % email) 669 logging.info("Using debug user %s. Override with --email" % email)
627 server = rpc_server_class( 670 server = HttpRpcServer(
628 server, 671 server,
629 lambda: (email, "password"), 672 lambda: (email, "password"),
630 host_override=host_override, 673 host_override=host_override,
631 extra_headers={"Cookie": 674 extra_headers={"Cookie":
632 'dev_appserver_login="%s:False"' % email}, 675 'dev_appserver_login="%s:False"' % email},
633 save_cookies=save_cookies, 676 save_cookies=save_cookies,
634 account_type=account_type) 677 account_type=account_type)
635 # Don't try to talk to ClientLogin. 678 # Don't try to talk to ClientLogin.
636 server.authenticated = True 679 server.authenticated = True
637 return server 680 return server
638 681
639 def GetUserCredentials(): 682 return HttpRpcServer(server,
640 """Prompts the user for a username and password.""" 683 KeyringCreds(server, host, email).GetUserCredentials,
641 # Create a local alias to the email variable to avoid Python's crazy 684 host_override=host_override,
642 # scoping rules. 685 save_cookies=save_cookies)
643 global keyring
644 local_email = email
645 if local_email is None:
646 local_email = GetEmail("Email (login for uploading to %s)" % server)
647 password = None
648 if keyring:
649 try:
650 password = keyring.get_password(host, local_email)
651 except:
652 # Sadly, we have to trap all errors here as
653 # gnomekeyring.IOError inherits from object. :/
654 print "Failed to get password from keyring"
655 keyring = None
656 if password is not None:
657 print "Using password from system keyring."
658 else:
659 password = getpass.getpass("Password for %s: " % local_email)
660 if keyring:
661 answer = raw_input("Store password in system keyring?(y/N) ").strip()
662 if answer == "y":
663 keyring.set_password(host, local_email, password)
664 return (local_email, password)
665
666 return rpc_server_class(server,
667 GetUserCredentials,
668 host_override=host_override,
669 save_cookies=save_cookies)
670 686
671 687
672 def EncodeMultipartFormData(fields, files): 688 def EncodeMultipartFormData(fields, files):
673 """Encode form fields for multipart/form-data. 689 """Encode form fields for multipart/form-data.
674 690
675 Args: 691 Args:
676 fields: A sequence of (name, value) elements for regular form fields. 692 fields: A sequence of (name, value) elements for regular form fields.
677 files: A sequence of (name, filename, value) elements for data to be 693 files: A sequence of (name, filename, value) elements for data to be
678 uploaded as files. 694 uploaded as files.
679 Returns: 695 Returns:
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 if self.options.revision: 1308 if self.options.revision:
1293 if ":" in self.options.revision: 1309 if ":" in self.options.revision:
1294 extra_args = self.options.revision.split(":", 1) + extra_args 1310 extra_args = self.options.revision.split(":", 1) + extra_args
1295 else: 1311 else:
1296 extra_args = [self.options.revision] + extra_args 1312 extra_args = [self.options.revision] + extra_args
1297 1313
1298 # --no-ext-diff is broken in some versions of Git, so try to work around 1314 # --no-ext-diff is broken in some versions of Git, so try to work around
1299 # this by overriding the environment (but there is still a problem if the 1315 # this by overriding the environment (but there is still a problem if the
1300 # git config key "diff.external" is used). 1316 # git config key "diff.external" is used).
1301 env = os.environ.copy() 1317 env = os.environ.copy()
1302 if 'GIT_EXTERNAL_DIFF' in env: del env['GIT_EXTERNAL_DIFF'] 1318 if "GIT_EXTERNAL_DIFF" in env:
1319 del env["GIT_EXTERNAL_DIFF"]
1303 # -M/-C will not print the diff for the deleted file when a file is renamed. 1320 # -M/-C will not print the diff for the deleted file when a file is renamed.
1304 # This is confusing because the original file will not be shown on the 1321 # This is confusing because the original file will not be shown on the
1305 # review when a file is renamed. So first get the diff of all deleted files, 1322 # review when a file is renamed. So, get a diff with ONLY deletes, then
1306 # then the diff of everything except deleted files with rename and copy 1323 # append a diff (with rename detection), without deletes.
1307 # support enabled.
1308 cmd = [ 1324 cmd = [
1309 "git", "diff", "--no-color", "--no-ext-diff", "--full-index", 1325 "git", "diff", "--no-color", "--no-ext-diff", "--full-index",
1310 "--ignore-submodules", 1326 "--ignore-submodules",
1311 ] 1327 ]
1312 diff = RunShell( 1328 diff = RunShell(
1313 cmd + ["--diff-filter=D"] + extra_args, env=env, silent_ok=True) 1329 cmd + ["--no-renames", "--diff-filter=D"] + extra_args,
1330 env=env, silent_ok=True)
1314 diff += RunShell( 1331 diff += RunShell(
1315 cmd + ["--find-copies-harder", "--diff-filter=ACMRT"] + extra_args, 1332 cmd + ["--find-copies-harder", "-l100000", "--diff-filter=AMCRT"]
1333 + extra_args,
1316 env=env, silent_ok=True) 1334 env=env, silent_ok=True)
1335
1317 # The CL could be only file deletion or not. So accept silent diff for both 1336 # The CL could be only file deletion or not. So accept silent diff for both
1318 # commands then check for an empty diff manually. 1337 # commands then check for an empty diff manually.
1319 if not diff: 1338 if not diff:
1320 ErrorExit("No output from %s" % (cmd + extra_args)) 1339 ErrorExit("No output from %s" % (cmd + extra_args))
1321 return diff 1340 return diff
1322 1341
1323 def GetUnknownFiles(self): 1342 def GetUnknownFiles(self):
1324 status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], 1343 status = RunShell(["git", "ls-files", "--exclude-standard", "--others"],
1325 silent_ok=True) 1344 silent_ok=True)
1326 return status.splitlines() 1345 return status.splitlines()
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after
2352 os.environ['LC_ALL'] = 'C' 2371 os.environ['LC_ALL'] = 'C'
2353 RealMain(sys.argv) 2372 RealMain(sys.argv)
2354 except KeyboardInterrupt: 2373 except KeyboardInterrupt:
2355 print 2374 print
2356 StatusUpdate("Interrupted.") 2375 StatusUpdate("Interrupted.")
2357 sys.exit(1) 2376 sys.exit(1)
2358 2377
2359 2378
2360 if __name__ == "__main__": 2379 if __name__ == "__main__":
2361 main() 2380 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