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

Side by Side Diff: third_party/upload.py

Issue 785433003: Update upload.py in depot_tools to infra.git@3d174a0959ba68a4cd83a5abce9f497e30bfce68 (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@fix_broken
Patch Set: Created 6 years 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 | 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 96
97 # Constants for version control names. Used by GuessVCSName. 97 # Constants for version control names. Used by GuessVCSName.
98 VCS_GIT = "Git" 98 VCS_GIT = "Git"
99 VCS_MERCURIAL = "Mercurial" 99 VCS_MERCURIAL = "Mercurial"
100 VCS_SUBVERSION = "Subversion" 100 VCS_SUBVERSION = "Subversion"
101 VCS_PERFORCE = "Perforce" 101 VCS_PERFORCE = "Perforce"
102 VCS_CVS = "CVS" 102 VCS_CVS = "CVS"
103 VCS_UNKNOWN = "Unknown" 103 VCS_UNKNOWN = "Unknown"
104 104
105 VCS = [ 105 VCS = [
106 { 106 {'name': VCS_MERCURIAL,
107 'name': VCS_MERCURIAL, 107 'aliases': ['hg', 'mercurial']},
108 'aliases': ['hg', 'mercurial'], 108 {'name': VCS_SUBVERSION,
109 }, { 109 'aliases': ['svn', 'subversion'],},
110 'name': VCS_SUBVERSION, 110 {'name': VCS_PERFORCE,
111 'aliases': ['svn', 'subversion'], 111 'aliases': ['p4', 'perforce']},
112 }, { 112 {'name': VCS_GIT,
113 'name': VCS_PERFORCE, 113 'aliases': ['git']},
114 'aliases': ['p4', 'perforce'], 114 {'name': VCS_CVS,
115 }, { 115 'aliases': ['cvs']},
116 'name': VCS_GIT, 116 ]
117 'aliases': ['git'], 117
118 }, {
119 'name': VCS_CVS,
120 'aliases': ['cvs'],
121 }]
122 118
123 VCS_SHORT_NAMES = [] # hg, svn, ... 119 VCS_SHORT_NAMES = [] # hg, svn, ...
124 VCS_ABBREVIATIONS = {} # alias: name, ... 120 VCS_ABBREVIATIONS = {} # alias: name, ...
125 for vcs in VCS: 121 for vcs in VCS:
126 VCS_SHORT_NAMES.append(min(vcs['aliases'], key=len)) 122 VCS_SHORT_NAMES.append(min(vcs['aliases'], key=len))
127 VCS_ABBREVIATIONS.update((alias, vcs['name']) for alias in vcs['aliases']) 123 VCS_ABBREVIATIONS.update((alias, vcs['name']) for alias in vcs['aliases'])
128 124
129 125
130 # OAuth 2.0-Related Constants 126 # OAuth 2.0-Related Constants
131 LOCALHOST_IP = '127.0.0.1' 127 LOCALHOST_IP = '127.0.0.1'
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 207
212 Args: 208 Args:
213 msg: The string to print. 209 msg: The string to print.
214 """ 210 """
215 if verbosity > 0: 211 if verbosity > 0:
216 print msg 212 print msg
217 213
218 214
219 def ErrorExit(msg): 215 def ErrorExit(msg):
220 """Print an error message to stderr and exit.""" 216 """Print an error message to stderr and exit."""
221 print >>sys.stderr, msg 217 print >> sys.stderr, msg
222 sys.exit(1) 218 sys.exit(1)
223 219
224 220
225 class ClientLoginError(urllib2.HTTPError): 221 class ClientLoginError(urllib2.HTTPError):
226 """Raised to indicate there was an error authenticating with ClientLogin.""" 222 """Raised to indicate there was an error authenticating with ClientLogin."""
227 223
228 def __init__(self, url, code, msg, headers, args): 224 def __init__(self, url, code, msg, headers, args):
229 urllib2.HTTPError.__init__(self, url, code, msg, headers, None) 225 urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
230 self.args = args 226 self.args = args
231 self._reason = args["Error"] 227 self._reason = args["Error"]
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 370
375 If we attempt to access the upload API without first obtaining an 371 If we attempt to access the upload API without first obtaining an
376 authentication cookie, it returns a 401 response (or a 302) and 372 authentication cookie, it returns a 401 response (or a 302) and
377 directs us to authenticate ourselves with ClientLogin. 373 directs us to authenticate ourselves with ClientLogin.
378 """ 374 """
379 for i in range(3): 375 for i in range(3):
380 credentials = self.auth_function() 376 credentials = self.auth_function()
381 try: 377 try:
382 auth_token = self._GetAuthToken(credentials[0], credentials[1]) 378 auth_token = self._GetAuthToken(credentials[0], credentials[1])
383 except ClientLoginError, e: 379 except ClientLoginError, e:
384 print >>sys.stderr, '' 380 print >> sys.stderr, ''
385 if e.reason == "BadAuthentication": 381 if e.reason == "BadAuthentication":
386 if e.info == "InvalidSecondFactor": 382 if e.info == "InvalidSecondFactor":
387 print >>sys.stderr, ( 383 print >> sys.stderr, (
388 "Use an application-specific password instead " 384 "Use an application-specific password instead "
389 "of your regular account password.\n" 385 "of your regular account password.\n"
390 "See http://www.google.com/" 386 "See http://www.google.com/"
391 "support/accounts/bin/answer.py?answer=185833") 387 "support/accounts/bin/answer.py?answer=185833")
392 else: 388 else:
393 print >>sys.stderr, "Invalid username or password." 389 print >> sys.stderr, "Invalid username or password."
394 elif e.reason == "CaptchaRequired": 390 elif e.reason == "CaptchaRequired":
395 print >>sys.stderr, ( 391 print >> sys.stderr, (
396 "Please go to\n" 392 "Please go to\n"
397 "https://www.google.com/accounts/DisplayUnlockCaptcha\n" 393 "https://www.google.com/accounts/DisplayUnlockCaptcha\n"
398 "and verify you are a human. Then try again.\n" 394 "and verify you are a human. Then try again.\n"
399 "If you are using a Google Apps account the URL is:\n" 395 "If you are using a Google Apps account the URL is:\n"
400 "https://www.google.com/a/yourdomain.com/UnlockCaptcha") 396 "https://www.google.com/a/yourdomain.com/UnlockCaptcha")
401 elif e.reason == "NotVerified": 397 elif e.reason == "NotVerified":
402 print >>sys.stderr, "Account not verified." 398 print >> sys.stderr, "Account not verified."
403 elif e.reason == "TermsNotAgreed": 399 elif e.reason == "TermsNotAgreed":
404 print >>sys.stderr, "User has not agreed to TOS." 400 print >> sys.stderr, "User has not agreed to TOS."
405 elif e.reason == "AccountDeleted": 401 elif e.reason == "AccountDeleted":
406 print >>sys.stderr, "The user account has been deleted." 402 print >> sys.stderr, "The user account has been deleted."
407 elif e.reason == "AccountDisabled": 403 elif e.reason == "AccountDisabled":
408 print >>sys.stderr, "The user account has been disabled." 404 print >> sys.stderr, "The user account has been disabled."
409 break 405 break
410 elif e.reason == "ServiceDisabled": 406 elif e.reason == "ServiceDisabled":
411 print >>sys.stderr, ("The user's access to the service has been " 407 print >> sys.stderr, ("The user's access to the service has been "
412 "disabled.") 408 "disabled.")
413 elif e.reason == "ServiceUnavailable": 409 elif e.reason == "ServiceUnavailable":
414 print >>sys.stderr, "The service is not available; try again later." 410 print >> sys.stderr, "The service is not available; try again later."
415 else: 411 else:
416 # Unknown error. 412 # Unknown error.
417 raise 413 raise
418 print >>sys.stderr, '' 414 print >> sys.stderr, ''
419 continue 415 continue
420 self._GetAuthCookie(auth_token) 416 self._GetAuthCookie(auth_token)
421 return 417 return
422 418
423 def Send(self, request_path, payload=None, 419 def Send(self, request_path, payload=None,
424 content_type="application/octet-stream", 420 content_type="application/octet-stream",
425 timeout=None, 421 timeout=None,
426 extra_headers=None, 422 extra_headers=None,
427 **kwargs): 423 **kwargs):
428 """Sends an RPC and returns the response. 424 """Sends an RPC and returns the response.
(...skipping 26 matching lines...) Expand all
455 args = dict(kwargs) 451 args = dict(kwargs)
456 url = "%s%s" % (self.host, request_path) 452 url = "%s%s" % (self.host, request_path)
457 if args: 453 if args:
458 url += "?" + urllib.urlencode(args) 454 url += "?" + urllib.urlencode(args)
459 req = self._CreateRequest(url=url, data=payload) 455 req = self._CreateRequest(url=url, data=payload)
460 req.add_header("Content-Type", content_type) 456 req.add_header("Content-Type", content_type)
461 if extra_headers: 457 if extra_headers:
462 for header, value in extra_headers.items(): 458 for header, value in extra_headers.items():
463 req.add_header(header, value) 459 req.add_header(header, value)
464 try: 460 try:
465 f = self.opener.open(req) 461 f = self.opener.open(req, timeout=70)
466 response = f.read() 462 response = f.read()
467 f.close() 463 f.close()
468 return response 464 return response
469 except urllib2.HTTPError, e: 465 except urllib2.HTTPError, e:
470 if tries > 3: 466 if tries > 3:
471 raise 467 raise
472 elif e.code == 401 or e.code == 302: 468 elif e.code == 401 or e.code == 302:
473 if not self.auth_function: 469 if not self.auth_function:
474 raise 470 raise
475 self._Authenticate() 471 self._Authenticate()
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 # Always chmod the cookie file 532 # Always chmod the cookie file
537 os.chmod(self.cookie_file, 0600) 533 os.chmod(self.cookie_file, 0600)
538 else: 534 else:
539 # Don't save cookies across runs of update.py. 535 # Don't save cookies across runs of update.py.
540 self.cookie_jar = cookielib.CookieJar() 536 self.cookie_jar = cookielib.CookieJar()
541 opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) 537 opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
542 return opener 538 return opener
543 539
544 540
545 class CondensedHelpFormatter(optparse.IndentedHelpFormatter): 541 class CondensedHelpFormatter(optparse.IndentedHelpFormatter):
546 """Frees more horizontal space by removing indentation from group 542 """Frees more horizontal space by removing indentation from group
547 options and collapsing arguments between short and long, e.g. 543 options and collapsing arguments between short and long, e.g.
548 '-o ARG, --opt=ARG' to -o --opt ARG""" 544 '-o ARG, --opt=ARG' to -o --opt ARG"""
549 545
550 def format_heading(self, heading): 546 def format_heading(self, heading):
551 return "%s:\n" % heading 547 return "%s:\n" % heading
552 548
553 def format_option(self, option): 549 def format_option(self, option):
554 self.dedent() 550 self.dedent()
555 res = optparse.HelpFormatter.format_option(self, option) 551 res = optparse.HelpFormatter.format_option(self, option)
556 self.indent() 552 self.indent()
557 return res 553 return res
558 554
559 def format_option_strings(self, option): 555 def format_option_strings(self, option):
560 self.set_long_opt_delimiter(" ") 556 self.set_long_opt_delimiter(" ")
561 optstr = optparse.HelpFormatter.format_option_strings(self, option) 557 optstr = optparse.HelpFormatter.format_option_strings(self, option)
562 optlist = optstr.split(", ") 558 optlist = optstr.split(", ")
563 if len(optlist) > 1: 559 if len(optlist) > 1:
564 if option.takes_value(): 560 if option.takes_value():
565 # strip METAVAR from all but the last option 561 # strip METAVAR from all but the last option
566 optlist = [x.split()[0] for x in optlist[:-1]] + optlist[-1:] 562 optlist = [x.split()[0] for x in optlist[:-1]] + optlist[-1:]
567 optstr = " ".join(optlist) 563 optstr = " ".join(optlist)
568 return optstr 564 return optstr
569 565
570 566
571 parser = optparse.OptionParser( 567 parser = optparse.OptionParser(
572 usage=("%prog [options] [-- diff_options] [path...]\n" 568 usage=("%prog [options] [-- diff_options] [path...]\n"
573 "See also: http://code.google.com/p/rietveld/wiki/UploadPyUsage"), 569 "See also: http://code.google.com/p/rietveld/wiki/UploadPyUsage"),
574 add_help_option=False, 570 add_help_option=False,
575 formatter=CondensedHelpFormatter() 571 formatter=CondensedHelpFormatter()
576 ) 572 )
577 parser.add_option("-h", "--help", action="store_true", 573 parser.add_option("-h", "--help", action="store_true",
578 help="Show this help message and exit.") 574 help="Show this help message and exit.")
579 parser.add_option("-y", "--assume_yes", action="store_true", 575 parser.add_option("-y", "--assume_yes", action="store_true",
580 dest="assume_yes", default=False, 576 dest="assume_yes", default=False,
581 help="Assume that the answer to yes/no questions is 'yes'.") 577 help="Assume that the answer to yes/no questions is 'yes'.")
582 # Logging 578 # Logging
583 group = parser.add_option_group("Logging options") 579 group = parser.add_option_group("Logging options")
584 group.add_option("-q", "--quiet", action="store_const", const=0, 580 group.add_option("-q", "--quiet", action="store_const", const=0,
585 dest="verbose", help="Print errors only.") 581 dest="verbose", help="Print errors only.")
586 group.add_option("-v", "--verbose", action="store_const", const=2, 582 group.add_option("-v", "--verbose", action="store_const", const=2,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 metavar="VCS", default=None, 670 metavar="VCS", default=None,
675 help=("Explicitly specify version control system (%s)" 671 help=("Explicitly specify version control system (%s)"
676 % ", ".join(VCS_SHORT_NAMES))) 672 % ", ".join(VCS_SHORT_NAMES)))
677 group.add_option("--emulate_svn_auto_props", action="store_true", 673 group.add_option("--emulate_svn_auto_props", action="store_true",
678 dest="emulate_svn_auto_props", default=False, 674 dest="emulate_svn_auto_props", default=False,
679 help=("Emulate Subversion's auto properties feature.")) 675 help=("Emulate Subversion's auto properties feature."))
680 # Git-specific 676 # Git-specific
681 group = parser.add_option_group("Git-specific options") 677 group = parser.add_option_group("Git-specific options")
682 group.add_option("--git_similarity", action="store", dest="git_similarity", 678 group.add_option("--git_similarity", action="store", dest="git_similarity",
683 metavar="SIM", type="int", default=50, 679 metavar="SIM", type="int", default=50,
684 help=("Set the minimum similarity index for detecting renames " 680 help=("Set the minimum similarity percentage for detecting "
685 "and copies. See `git diff -C`. (default 50).")) 681 "renames and copies. See `git diff -C`. (default 50)."))
682 group.add_option("--git_only_search_patch", action="store_false", default=True,
683 dest='git_find_copies_harder',
684 help="Removes --find-copies-harder when seaching for copies")
686 group.add_option("--git_no_find_copies", action="store_false", default=True, 685 group.add_option("--git_no_find_copies", action="store_false", default=True,
687 dest="git_find_copies", 686 dest="git_find_copies",
688 help=("Prevents git from looking for copies (default off).")) 687 help=("Prevents git from looking for copies (default off)."))
689 # Perforce-specific 688 # Perforce-specific
690 group = parser.add_option_group("Perforce-specific options " 689 group = parser.add_option_group("Perforce-specific options "
691 "(overrides P4 environment variables)") 690 "(overrides P4 environment variables)")
692 group.add_option("--p4_port", action="store", dest="p4_port", 691 group.add_option("--p4_port", action="store", dest="p4_port",
693 metavar="P4_PORT", default=None, 692 metavar="P4_PORT", default=None,
694 help=("Perforce server and port (optional)")) 693 help=("Perforce server and port (optional)"))
695 group.add_option("--p4_changelist", action="store", dest="p4_changelist", 694 group.add_option("--p4_changelist", action="store", dest="p4_changelist",
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 """Helper to guess the content-type from the filename.""" 1002 """Helper to guess the content-type from the filename."""
1004 return mimetypes.guess_type(filename)[0] or 'application/octet-stream' 1003 return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
1005 1004
1006 1005
1007 # Use a shell for subcommands on Windows to get a PATH search. 1006 # Use a shell for subcommands on Windows to get a PATH search.
1008 use_shell = sys.platform.startswith("win") 1007 use_shell = sys.platform.startswith("win")
1009 1008
1010 def RunShellWithReturnCodeAndStderr(command, print_output=False, 1009 def RunShellWithReturnCodeAndStderr(command, print_output=False,
1011 universal_newlines=True, 1010 universal_newlines=True,
1012 env=os.environ): 1011 env=os.environ):
1013 """Executes a command and returns the output from stdout, stderr and the retur n code. 1012 """Run a command and return output from stdout, stderr and the return code.
1014 1013
1015 Args: 1014 Args:
1016 command: Command to execute. 1015 command: Command to execute.
1017 print_output: If True, the output is printed to stdout. 1016 print_output: If True, the output is printed to stdout.
1018 If False, both stdout and stderr are ignored. 1017 If False, both stdout and stderr are ignored.
1019 universal_newlines: Use universal_newlines flag (default: True). 1018 universal_newlines: Use universal_newlines flag (default: True).
1020 1019
1021 Returns: 1020 Returns:
1022 Tuple (stdout, stderr, return code) 1021 Tuple (stdout, stderr, return code)
1023 """ 1022 """
(...skipping 10 matching lines...) Expand all
1034 if not line: 1033 if not line:
1035 break 1034 break
1036 print line.strip("\n") 1035 print line.strip("\n")
1037 output_array.append(line) 1036 output_array.append(line)
1038 output = "".join(output_array) 1037 output = "".join(output_array)
1039 else: 1038 else:
1040 output = p.stdout.read() 1039 output = p.stdout.read()
1041 p.wait() 1040 p.wait()
1042 errout = p.stderr.read() 1041 errout = p.stderr.read()
1043 if print_output and errout: 1042 if print_output and errout:
1044 print >>sys.stderr, errout 1043 print >> sys.stderr, errout
1045 p.stdout.close() 1044 p.stdout.close()
1046 p.stderr.close() 1045 p.stderr.close()
1047 return output, errout, p.returncode 1046 return output, errout, p.returncode
1048 1047
1049 def RunShellWithReturnCode(command, print_output=False, 1048 def RunShellWithReturnCode(command, print_output=False,
1050 universal_newlines=True, 1049 universal_newlines=True,
1051 env=os.environ): 1050 env=os.environ):
1052 """Executes a command and returns the output from stdout and the return code." "" 1051 """Run a command and return output from stdout and the return code."""
1053 out, err, retcode = RunShellWithReturnCodeAndStderr(command, print_output, 1052 out, err, retcode = RunShellWithReturnCodeAndStderr(command, print_output,
1054 universal_newlines, env) 1053 universal_newlines, env)
1055 return out, retcode 1054 return out, retcode
1056 1055
1057 def RunShell(command, silent_ok=False, universal_newlines=True, 1056 def RunShell(command, silent_ok=False, universal_newlines=True,
1058 print_output=False, env=os.environ): 1057 print_output=False, env=os.environ):
1059 data, retcode = RunShellWithReturnCode(command, print_output, 1058 data, retcode = RunShellWithReturnCode(command, print_output,
1060 universal_newlines, env) 1059 universal_newlines, env)
1061 if retcode: 1060 if retcode:
1062 ErrorExit("Got error status from %s:\n%s" % (command, data)) 1061 ErrorExit("Got error status from %s:\n%s" % (command, data))
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 1216
1218 for t in threads: 1217 for t in threads:
1219 print t.get(timeout=60) 1218 print t.get(timeout=60)
1220 1219
1221 1220
1222 def IsImage(self, filename): 1221 def IsImage(self, filename):
1223 """Returns true if the filename has an image extension.""" 1222 """Returns true if the filename has an image extension."""
1224 mimetype = mimetypes.guess_type(filename)[0] 1223 mimetype = mimetypes.guess_type(filename)[0]
1225 if not mimetype: 1224 if not mimetype:
1226 return False 1225 return False
1227 return mimetype.startswith("image/") and not mimetype.startswith("image/svg" ) 1226 return (mimetype.startswith("image/") and
1227 not mimetype.startswith("image/svg"))
1228 1228
1229 def IsBinaryData(self, data): 1229 def IsBinaryData(self, data):
1230 """Returns true if data contains a null byte.""" 1230 """Returns true if data contains a null byte."""
1231 # Derived from how Mercurial's heuristic, see 1231 # Derived from how Mercurial's heuristic, see
1232 # http://selenic.com/hg/file/848a6658069e/mercurial/util.py#l229 1232 # http://selenic.com/hg/file/848a6658069e/mercurial/util.py#l229
1233 return bool(data and "\0" in data) 1233 return bool(data and "\0" in data)
1234 1234
1235 1235
1236 class SubversionVCS(VersionControlSystem): 1236 class SubversionVCS(VersionControlSystem):
1237 """Implementation of the VersionControlSystem interface for Subversion.""" 1237 """Implementation of the VersionControlSystem interface for Subversion."""
(...skipping 25 matching lines...) Expand all
1263 1263
1264 def _GuessBase(self, required): 1264 def _GuessBase(self, required):
1265 """Returns base URL for current diff. 1265 """Returns base URL for current diff.
1266 1266
1267 Args: 1267 Args:
1268 required: If true, exits if the url can't be guessed, otherwise None is 1268 required: If true, exits if the url can't be guessed, otherwise None is
1269 returned. 1269 returned.
1270 """ 1270 """
1271 url = self._GetInfo("URL") 1271 url = self._GetInfo("URL")
1272 if url: 1272 if url:
1273 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) 1273 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
1274 guess = "" 1274 guess = ""
1275 # TODO(anatoli) - repository specific hacks should be handled by server 1275 # TODO(anatoli) - repository specific hacks should be handled by server
1276 if netloc == "svn.python.org" and scheme == "svn+ssh": 1276 if netloc == "svn.python.org" and scheme == "svn+ssh":
1277 path = "projects" + path 1277 path = "projects" + path
1278 scheme = "http" 1278 scheme = "http"
1279 guess = "Python " 1279 guess = "Python "
1280 elif netloc.endswith(".googlecode.com"): 1280 elif netloc.endswith(".googlecode.com"):
1281 scheme = "http" 1281 scheme = "http"
1282 guess = "Google Code " 1282 guess = "Google Code "
1283 path = path + "/" 1283 path = path + "/"
1284 base = urlparse.urlunparse((scheme, netloc, path, params, 1284 base = urlparse.urlunparse((scheme, netloc, path, params,
1285 query, fragment)) 1285 query, fragment))
1286 LOGGER.info("Guessed %sbase = %s", guess, base) 1286 LOGGER.info("Guessed %sbase = %s", guess, base)
1287 return base 1287 return base
1288 if required: 1288 if required:
1289 ErrorExit("Can't find URL in output from svn info") 1289 ErrorExit("Can't find URL in output from svn info")
1290 return None 1290 return None
1291 1291
1292 def _GetInfo(self, key): 1292 def _GetInfo(self, key):
1293 """Parses 'svn info' for current dir. Returns value for key or None""" 1293 """Parses 'svn info' for current dir. Returns value for key or None"""
1294 for line in RunShell(["svn", "info"]).splitlines(): 1294 for line in RunShell(["svn", "info"]).splitlines():
1295 if line.startswith(key + ": "): 1295 if line.startswith(key + ": "):
1296 return line.split(":", 1)[1].strip() 1296 return line.split(":", 1)[1].strip()
1297 1297
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 'Id': ['Id'], 1332 'Id': ['Id'],
1333 1333
1334 # Aliases 1334 # Aliases
1335 'LastChangedDate': ['LastChangedDate', 'Date'], 1335 'LastChangedDate': ['LastChangedDate', 'Date'],
1336 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'], 1336 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'],
1337 'LastChangedBy': ['LastChangedBy', 'Author'], 1337 'LastChangedBy': ['LastChangedBy', 'Author'],
1338 'URL': ['URL', 'HeadURL'], 1338 'URL': ['URL', 'HeadURL'],
1339 } 1339 }
1340 1340
1341 def repl(m): 1341 def repl(m):
1342 if m.group(2): 1342 if m.group(2):
1343 return "$%s::%s$" % (m.group(1), " " * len(m.group(3))) 1343 return "$%s::%s$" % (m.group(1), " " * len(m.group(3)))
1344 return "$%s$" % m.group(1) 1344 return "$%s$" % m.group(1)
1345
1345 keywords = [keyword 1346 keywords = [keyword
1346 for name in keyword_str.split(" ") 1347 for name in keyword_str.split(" ")
1347 for keyword in svn_keywords.get(name, [])] 1348 for keyword in svn_keywords.get(name, [])]
1348 return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content) 1349 return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content)
1349 1350
1350 def GetUnknownFiles(self): 1351 def GetUnknownFiles(self):
1351 status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True) 1352 status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True)
1352 unknown_files = [] 1353 unknown_files = []
1353 for line in status.split("\n"): 1354 for line in status.split("\n"):
1354 if line and line[0] == "?": 1355 if line and line[0] == "?":
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 # the correct status for a file. 1388 # the correct status for a file.
1388 else: 1389 else:
1389 dirname, relfilename = os.path.split(filename) 1390 dirname, relfilename = os.path.split(filename)
1390 if dirname not in self.svnls_cache: 1391 if dirname not in self.svnls_cache:
1391 cmd = ["svn", "list", "-r", self.rev_start, 1392 cmd = ["svn", "list", "-r", self.rev_start,
1392 self._EscapeFilename(dirname) or "."] 1393 self._EscapeFilename(dirname) or "."]
1393 out, err, returncode = RunShellWithReturnCodeAndStderr(cmd) 1394 out, err, returncode = RunShellWithReturnCodeAndStderr(cmd)
1394 if returncode: 1395 if returncode:
1395 # Directory might not yet exist at start revison 1396 # Directory might not yet exist at start revison
1396 # svn: Unable to find repository location for 'abc' in revision nnn 1397 # svn: Unable to find repository location for 'abc' in revision nnn
1397 if re.match('^svn: Unable to find repository location for .+ in revisi on \d+', err): 1398 if re.match('^svn: Unable to find repository location '
1399 'for .+ in revision \d+', err):
1398 old_files = () 1400 old_files = ()
1399 else: 1401 else:
1400 ErrorExit("Failed to get status for %s:\n%s" % (filename, err)) 1402 ErrorExit("Failed to get status for %s:\n%s" % (filename, err))
1401 else: 1403 else:
1402 old_files = out.splitlines() 1404 old_files = out.splitlines()
1403 args = ["svn", "list"] 1405 args = ["svn", "list"]
1404 if self.rev_end: 1406 if self.rev_end:
1405 args += ["-r", self.rev_end] 1407 args += ["-r", self.rev_end]
1406 cmd = args + [self._EscapeFilename(dirname) or "."] 1408 cmd = args + [self._EscapeFilename(dirname) or "."]
1407 out, returncode = RunShellWithReturnCode(cmd) 1409 out, returncode = RunShellWithReturnCode(cmd)
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 # git config key "diff.external" is used). 1611 # git config key "diff.external" is used).
1610 env = os.environ.copy() 1612 env = os.environ.copy()
1611 if "GIT_EXTERNAL_DIFF" in env: 1613 if "GIT_EXTERNAL_DIFF" in env:
1612 del env["GIT_EXTERNAL_DIFF"] 1614 del env["GIT_EXTERNAL_DIFF"]
1613 # -M/-C will not print the diff for the deleted file when a file is renamed. 1615 # -M/-C will not print the diff for the deleted file when a file is renamed.
1614 # This is confusing because the original file will not be shown on the 1616 # This is confusing because the original file will not be shown on the
1615 # review when a file is renamed. So, get a diff with ONLY deletes, then 1617 # review when a file is renamed. So, get a diff with ONLY deletes, then
1616 # append a diff (with rename detection), without deletes. 1618 # append a diff (with rename detection), without deletes.
1617 cmd = [ 1619 cmd = [
1618 "git", "diff", "--no-color", "--no-ext-diff", "--full-index", 1620 "git", "diff", "--no-color", "--no-ext-diff", "--full-index",
1619 "--ignore-submodules", 1621 "--ignore-submodules", "--src-prefix=a/", "--dst-prefix=b/",
1620 ] 1622 ]
1621 diff = RunShell( 1623 diff = RunShell(
1622 cmd + ["--no-renames", "--diff-filter=D"] + extra_args, 1624 cmd + ["--no-renames", "--diff-filter=D"] + extra_args,
1623 env=env, silent_ok=True) 1625 env=env, silent_ok=True)
1626 assert 0 <= self.options.git_similarity <= 100
1624 if self.options.git_find_copies: 1627 if self.options.git_find_copies:
1625 similarity_options = ["--find-copies-harder", "-l100000", 1628 similarity_options = ["-l100000", "-C%d%%" % self.options.git_similarity]
1626 "-C%s" % self.options.git_similarity ] 1629 if self.options.git_find_copies_harder:
1630 similarity_options.append("--find-copies-harder")
1627 else: 1631 else:
1628 similarity_options = ["-M%s" % self.options.git_similarity ] 1632 similarity_options = ["-M%d%%" % self.options.git_similarity ]
1629 diff += RunShell( 1633 diff += RunShell(
1630 cmd + ["--diff-filter=AMCRT"] + similarity_options + extra_args, 1634 cmd + ["--diff-filter=AMCRT"] + similarity_options + extra_args,
1631 env=env, silent_ok=True) 1635 env=env, silent_ok=True)
1632 1636
1633 # The CL could be only file deletion or not. So accept silent diff for both 1637 # The CL could be only file deletion or not. So accept silent diff for both
1634 # commands then check for an empty diff manually. 1638 # commands then check for an empty diff manually.
1635 if not diff: 1639 if not diff:
1636 ErrorExit("No output from %s" % (cmd + extra_args)) 1640 ErrorExit("No output from %s" % (cmd + extra_args))
1637 return diff 1641 return diff
1638 1642
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 diffData.base_rev = fstat["headRev"] # Re-adding a deleted file 2083 diffData.base_rev = fstat["headRev"] # Re-adding a deleted file
2080 else: 2084 else:
2081 diffData.base_rev = "0" # Brand new file 2085 diffData.base_rev = "0" # Brand new file
2082 diffData.working_copy = False 2086 diffData.working_copy = False
2083 rel_path = self.GetLocalFilename(diffData.filename) 2087 rel_path = self.GetLocalFilename(diffData.filename)
2084 diffData.file_body = open(rel_path, 'r').read() 2088 diffData.file_body = open(rel_path, 'r').read()
2085 # Replicate svn's list of changed lines 2089 # Replicate svn's list of changed lines
2086 line_count = len(diffData.file_body.splitlines()) 2090 line_count = len(diffData.file_body.splitlines())
2087 diffData.change_summary = "@@ -0,0 +1" 2091 diffData.change_summary = "@@ -0,0 +1"
2088 if line_count > 1: 2092 if line_count > 1:
2089 diffData.change_summary += ",%d" % line_count 2093 diffData.change_summary += ",%d" % line_count
2090 diffData.change_summary += " @@" 2094 diffData.change_summary += " @@"
2091 diffData.prefix = "+" 2095 diffData.prefix = "+"
2092 return diffData 2096 return diffData
2093 2097
2094 def GenerateDeleteDiff(diffData): 2098 def GenerateDeleteDiff(diffData):
2095 diffData.base_rev = self.GetBaseRevision(diffData.filename) 2099 diffData.base_rev = self.GetBaseRevision(diffData.filename)
2096 is_base_binary = self.IsBaseBinary(diffData.filename) 2100 is_base_binary = self.IsBaseBinary(diffData.filename)
2097 # For deletes, base_filename == filename 2101 # For deletes, base_filename == filename
2098 diffData.file_body = self.GetFileContent(diffData.base_filename, 2102 diffData.file_body = self.GetFileContent(diffData.base_filename,
2099 None, 2103 None,
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
2706 os.environ['LC_ALL'] = 'C' 2710 os.environ['LC_ALL'] = 'C'
2707 RealMain(sys.argv) 2711 RealMain(sys.argv)
2708 except KeyboardInterrupt: 2712 except KeyboardInterrupt:
2709 print 2713 print
2710 StatusUpdate("Interrupted.") 2714 StatusUpdate("Interrupted.")
2711 sys.exit(1) 2715 sys.exit(1)
2712 2716
2713 2717
2714 if __name__ == "__main__": 2718 if __name__ == "__main__":
2715 main() 2719 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