| 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 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 os.close(fd) | 454 os.close(fd) |
| 455 # Always chmod the cookie file | 455 # Always chmod the cookie file |
| 456 os.chmod(self.cookie_file, 0600) | 456 os.chmod(self.cookie_file, 0600) |
| 457 else: | 457 else: |
| 458 # Don't save cookies across runs of update.py. | 458 # Don't save cookies across runs of update.py. |
| 459 self.cookie_jar = cookielib.CookieJar() | 459 self.cookie_jar = cookielib.CookieJar() |
| 460 opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) | 460 opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) |
| 461 return opener | 461 return opener |
| 462 | 462 |
| 463 | 463 |
| 464 class CondensedHelpFormatter(optparse.IndentedHelpFormatter): |
| 465 """Frees more horizontal space by removing indentation from group |
| 466 options and collapsing arguments between short and long, e.g. |
| 467 '-o ARG, --opt=ARG' to -o --opt ARG""" |
| 468 |
| 469 def format_heading(self, heading): |
| 470 return "%s:\n" % heading |
| 471 |
| 472 def format_option(self, option): |
| 473 self.dedent() |
| 474 res = optparse.HelpFormatter.format_option(self, option) |
| 475 self.indent() |
| 476 return res |
| 477 |
| 478 def format_option_strings(self, option): |
| 479 self.set_long_opt_delimiter(" ") |
| 480 optstr = optparse.HelpFormatter.format_option_strings(self, option) |
| 481 optlist = optstr.split(", ") |
| 482 if len(optlist) > 1: |
| 483 if option.takes_value(): |
| 484 # strip METAVAR from all but the last option |
| 485 optlist = [x.split()[0] for x in optlist[:-1]] + optlist[-1:] |
| 486 optstr = " ".join(optlist) |
| 487 return optstr |
| 488 |
| 489 |
| 464 parser = optparse.OptionParser( | 490 parser = optparse.OptionParser( |
| 465 usage="%prog [options] [-- diff_options] [path...]") | 491 usage="%prog [options] [-- diff_options] [path...]", |
| 492 add_help_option=False, |
| 493 formatter=CondensedHelpFormatter() |
| 494 ) |
| 495 parser.add_option("-h", "--help", action="store_true", |
| 496 help="Show this help message and exit.") |
| 466 parser.add_option("-y", "--assume_yes", action="store_true", | 497 parser.add_option("-y", "--assume_yes", action="store_true", |
| 467 dest="assume_yes", default=False, | 498 dest="assume_yes", default=False, |
| 468 help="Assume that the answer to yes/no questions is 'yes'.") | 499 help="Assume that the answer to yes/no questions is 'yes'.") |
| 469 # Logging | 500 # Logging |
| 470 group = parser.add_option_group("Logging options") | 501 group = parser.add_option_group("Logging options") |
| 471 group.add_option("-q", "--quiet", action="store_const", const=0, | 502 group.add_option("-q", "--quiet", action="store_const", const=0, |
| 472 dest="verbose", help="Print errors only.") | 503 dest="verbose", help="Print errors only.") |
| 473 group.add_option("-v", "--verbose", action="store_const", const=2, | 504 group.add_option("-v", "--verbose", action="store_const", const=2, |
| 474 dest="verbose", default=1, | 505 dest="verbose", default=1, |
| 475 help="Print info level logs.") | 506 help="Print info level logs.") |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 # Upload options | 552 # Upload options |
| 522 group = parser.add_option_group("Patch options") | 553 group = parser.add_option_group("Patch options") |
| 523 group.add_option("-m", "--message", action="store", dest="message", | 554 group.add_option("-m", "--message", action="store", dest="message", |
| 524 metavar="MESSAGE", default=None, | 555 metavar="MESSAGE", default=None, |
| 525 help="A message to identify the patch. " | 556 help="A message to identify the patch. " |
| 526 "Will prompt if omitted.") | 557 "Will prompt if omitted.") |
| 527 group.add_option("-i", "--issue", type="int", action="store", | 558 group.add_option("-i", "--issue", type="int", action="store", |
| 528 metavar="ISSUE", default=None, | 559 metavar="ISSUE", default=None, |
| 529 help="Issue number to which to add. Defaults to new issue.") | 560 help="Issue number to which to add. Defaults to new issue.") |
| 530 group.add_option("--base_url", action="store", dest="base_url", default=None, | 561 group.add_option("--base_url", action="store", dest="base_url", default=None, |
| 531 help="Base repository URL (listed as \"Base URL\" when " | 562 help="Base URL path for files (listed as \"Base URL\" when " |
| 532 "viewing issue). If omitted, will be guessed automatically " | 563 "viewing issue). If omitted, will be guessed automatically " |
| 533 "for SVN repos and left blank for others.") | 564 "for SVN repos and left blank for others.") |
| 534 group.add_option("--download_base", action="store_true", | 565 group.add_option("--download_base", action="store_true", |
| 535 dest="download_base", default=False, | 566 dest="download_base", default=False, |
| 536 help="Base files will be downloaded by the server " | 567 help="Base files will be downloaded by the server " |
| 537 "(side-by-side diffs may not work on files with CRs).") | 568 "(side-by-side diffs may not work on files with CRs).") |
| 538 group.add_option("--rev", action="store", dest="revision", | 569 group.add_option("--rev", action="store", dest="revision", |
| 539 metavar="REV", default=None, | 570 metavar="REV", default=None, |
| 540 help="Base revision/branch/tree to diff against. Use " | 571 help="Base revision/branch/tree to diff against. Use " |
| 541 "rev1:rev2 range to review already committed changeset.") | 572 "rev1:rev2 range to review already committed changeset.") |
| 542 group.add_option("--send_mail", action="store_true", | 573 group.add_option("--send_mail", action="store_true", |
| 543 dest="send_mail", default=False, | 574 dest="send_mail", default=False, |
| 544 help="Send notification email to reviewers.") | 575 help="Send notification email to reviewers.") |
| 545 group.add_option("-p", "--send_patch", action="store_true", | 576 group.add_option("-p", "--send_patch", action="store_true", |
| 546 dest="send_patch", default=False, | 577 dest="send_patch", default=False, |
| 547 help="Send notification email to reviewers, with a diff of " | 578 help="Same as --send_mail, but include diff as an " |
| 548 "the changes included as an attachment instead of " | 579 "attachment, and prepend email subject with 'PATCH:'.") |
| 549 "inline. Also prepends 'PATCH:' to the email subject. " | |
| 550 "(implies --send_mail)") | |
| 551 group.add_option("--vcs", action="store", dest="vcs", | 580 group.add_option("--vcs", action="store", dest="vcs", |
| 552 metavar="VCS", default=None, | 581 metavar="VCS", default=None, |
| 553 help=("Version control system (optional, usually upload.py " | 582 help=("Version control system (optional, usually upload.py " |
| 554 "already guesses the right VCS).")) | 583 "already guesses the right VCS).")) |
| 555 group.add_option("--emulate_svn_auto_props", action="store_true", | 584 group.add_option("--emulate_svn_auto_props", action="store_true", |
| 556 dest="emulate_svn_auto_props", default=False, | 585 dest="emulate_svn_auto_props", default=False, |
| 557 help=("Emulate Subversion's auto properties feature.")) | 586 help=("Emulate Subversion's auto properties feature.")) |
| 558 # Perforce-specific | 587 # Perforce-specific |
| 559 group = parser.add_option_group("Perforce-specific options " | 588 group = parser.add_option_group("Perforce-specific options " |
| 560 "(overrides P4 environment variables)") | 589 "(overrides P4 environment variables)") |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 class VersionControlSystem(object): | 778 class VersionControlSystem(object): |
| 750 """Abstract base class providing an interface to the VCS.""" | 779 """Abstract base class providing an interface to the VCS.""" |
| 751 | 780 |
| 752 def __init__(self, options): | 781 def __init__(self, options): |
| 753 """Constructor. | 782 """Constructor. |
| 754 | 783 |
| 755 Args: | 784 Args: |
| 756 options: Command line options. | 785 options: Command line options. |
| 757 """ | 786 """ |
| 758 self.options = options | 787 self.options = options |
| 788 |
| 789 def GetGUID(self): |
| 790 """Return string to distinguish the repository from others, for example to |
| 791 query all opened review issues for it""" |
| 792 raise NotImplementedError( |
| 793 "abstract method -- subclass %s must override" % self.__class__) |
| 759 | 794 |
| 760 def PostProcessDiff(self, diff): | 795 def PostProcessDiff(self, diff): |
| 761 """Return the diff with any special post processing this VCS needs, e.g. | 796 """Return the diff with any special post processing this VCS needs, e.g. |
| 762 to include an svn-style "Index:".""" | 797 to include an svn-style "Index:".""" |
| 763 return diff | 798 return diff |
| 764 | 799 |
| 765 def GenerateDiff(self, args): | 800 def GenerateDiff(self, args): |
| 766 """Return the current diff as a string. | 801 """Return the current diff as a string. |
| 767 | 802 |
| 768 Args: | 803 Args: |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 self.rev_end = match.group(3) | 938 self.rev_end = match.group(3) |
| 904 else: | 939 else: |
| 905 self.rev_start = self.rev_end = None | 940 self.rev_start = self.rev_end = None |
| 906 # Cache output from "svn list -r REVNO dirname". | 941 # Cache output from "svn list -r REVNO dirname". |
| 907 # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). | 942 # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). |
| 908 self.svnls_cache = {} | 943 self.svnls_cache = {} |
| 909 # Base URL is required to fetch files deleted in an older revision. | 944 # Base URL is required to fetch files deleted in an older revision. |
| 910 # Result is cached to not guess it over and over again in GetBaseFile(). | 945 # Result is cached to not guess it over and over again in GetBaseFile(). |
| 911 required = self.options.download_base or self.options.revision is not None | 946 required = self.options.download_base or self.options.revision is not None |
| 912 self.svn_base = self._GuessBase(required) | 947 self.svn_base = self._GuessBase(required) |
| 948 |
| 949 def GetGUID(self): |
| 950 return self._GetInfo("Repository UUID") |
| 913 | 951 |
| 914 def GuessBase(self, required): | 952 def GuessBase(self, required): |
| 915 """Wrapper for _GuessBase.""" | 953 """Wrapper for _GuessBase.""" |
| 916 return self.svn_base | 954 return self.svn_base |
| 917 | 955 |
| 918 def _GuessBase(self, required): | 956 def _GuessBase(self, required): |
| 919 """Returns base URL for current diff. | 957 """Returns base URL for current diff. |
| 920 | 958 |
| 921 Args: | 959 Args: |
| 922 required: If true, exits if the url can't be guessed, otherwise None is | 960 required: If true, exits if the url can't be guessed, otherwise None is |
| 923 returned. | 961 returned. |
| 924 """ | 962 """ |
| 925 info = RunShell(["svn", "info"]) | 963 url = self._GetInfo("URL") |
| 926 for line in info.splitlines(): | 964 if url: |
| 927 if line.startswith("URL: "): | |
| 928 url = line.split()[1] | |
| 929 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) | 965 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) |
| 930 guess = "" | 966 guess = "" |
| 967 # TODO(anatoli) - repository specific hacks should be handled by server |
| 931 if netloc == "svn.python.org" and scheme == "svn+ssh": | 968 if netloc == "svn.python.org" and scheme == "svn+ssh": |
| 932 path = "projects" + path | 969 path = "projects" + path |
| 933 scheme = "http" | 970 scheme = "http" |
| 934 guess = "Python " | 971 guess = "Python " |
| 935 elif netloc.endswith(".googlecode.com"): | 972 elif netloc.endswith(".googlecode.com"): |
| 936 scheme = "http" | 973 scheme = "http" |
| 937 guess = "Google Code " | 974 guess = "Google Code " |
| 938 path = path + "/" | 975 path = path + "/" |
| 939 base = urlparse.urlunparse((scheme, netloc, path, params, | 976 base = urlparse.urlunparse((scheme, netloc, path, params, |
| 940 query, fragment)) | 977 query, fragment)) |
| 941 logging.info("Guessed %sbase = %s", guess, base) | 978 logging.info("Guessed %sbase = %s", guess, base) |
| 942 return base | 979 return base |
| 943 if required: | 980 if required: |
| 944 ErrorExit("Can't find URL in output from svn info") | 981 ErrorExit("Can't find URL in output from svn info") |
| 945 return None | 982 return None |
| 983 |
| 984 def _GetInfo(self, key): |
| 985 """Parses 'svn info' for current dir. Returns value for key or None""" |
| 986 for line in RunShell(["svn", "info"]).splitlines(): |
| 987 if line.startswith(key + ": "): |
| 988 return line.split(":", 1)[1].strip() |
| 946 | 989 |
| 947 def _EscapeFilename(self, filename): | 990 def _EscapeFilename(self, filename): |
| 948 """Escapes filename for SVN commands.""" | 991 """Escapes filename for SVN commands.""" |
| 949 if "@" in filename and not filename.endswith("@"): | 992 if "@" in filename and not filename.endswith("@"): |
| 950 filename = "%s@" % filename | 993 filename = "%s@" % filename |
| 951 return filename | 994 return filename |
| 952 | 995 |
| 953 def GenerateDiff(self, args): | 996 def GenerateDiff(self, args): |
| 954 cmd = ["svn", "diff"] | 997 cmd = ["svn", "diff"] |
| 955 if self.options.revision: | 998 if self.options.revision: |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 class GitVCS(VersionControlSystem): | 1216 class GitVCS(VersionControlSystem): |
| 1174 """Implementation of the VersionControlSystem interface for Git.""" | 1217 """Implementation of the VersionControlSystem interface for Git.""" |
| 1175 | 1218 |
| 1176 def __init__(self, options): | 1219 def __init__(self, options): |
| 1177 super(GitVCS, self).__init__(options) | 1220 super(GitVCS, self).__init__(options) |
| 1178 # Map of filename -> (hash before, hash after) of base file. | 1221 # Map of filename -> (hash before, hash after) of base file. |
| 1179 # Hashes for "no such file" are represented as None. | 1222 # Hashes for "no such file" are represented as None. |
| 1180 self.hashes = {} | 1223 self.hashes = {} |
| 1181 # Map of new filename -> old filename for renames. | 1224 # Map of new filename -> old filename for renames. |
| 1182 self.renames = {} | 1225 self.renames = {} |
| 1226 |
| 1227 def GetGUID(self): |
| 1228 revlist = RunShell("git rev-list --parents HEAD".split()).splitlines() |
| 1229 # M-A: Return the 1st root hash, there could be multiple when a |
| 1230 # subtree is merged. In that case, more analysis would need to |
| 1231 # be done to figure out which HEAD is the 'most representative'. |
| 1232 for r in revlist: |
| 1233 if ' ' not in r: |
| 1234 return r |
| 1183 | 1235 |
| 1184 def PostProcessDiff(self, gitdiff): | 1236 def PostProcessDiff(self, gitdiff): |
| 1185 """Converts the diff output to include an svn-style "Index:" line as well | 1237 """Converts the diff output to include an svn-style "Index:" line as well |
| 1186 as record the hashes of the files, so we can upload them along with our | 1238 as record the hashes of the files, so we can upload them along with our |
| 1187 diff.""" | 1239 diff.""" |
| 1188 # Special used by git to indicate "no such content". | 1240 # Special used by git to indicate "no such content". |
| 1189 NULL_HASH = "0"*40 | 1241 NULL_HASH = "0"*40 |
| 1190 | 1242 |
| 1191 def IsFileNew(filename): | 1243 def IsFileNew(filename): |
| 1192 return filename in self.hashes and self.hashes[filename][0] is None | 1244 return filename in self.hashes and self.hashes[filename][0] is None |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 def GetBaseFile(self, filename): | 1336 def GetBaseFile(self, filename): |
| 1285 hash_before, hash_after = self.hashes.get(filename, (None,None)) | 1337 hash_before, hash_after = self.hashes.get(filename, (None,None)) |
| 1286 base_content = None | 1338 base_content = None |
| 1287 new_content = None | 1339 new_content = None |
| 1288 status = None | 1340 status = None |
| 1289 | 1341 |
| 1290 if filename in self.renames: | 1342 if filename in self.renames: |
| 1291 status = "A +" # Match svn attribute name for renames. | 1343 status = "A +" # Match svn attribute name for renames. |
| 1292 if filename not in self.hashes: | 1344 if filename not in self.hashes: |
| 1293 # If a rename doesn't change the content, we never get a hash. | 1345 # If a rename doesn't change the content, we never get a hash. |
| 1294 base_content = RunShell(["git", "show", "HEAD:" + filename]) | 1346 base_content = RunShell( |
| 1347 ["git", "show", "HEAD:" + filename], silent_ok=True) |
| 1295 elif not hash_before: | 1348 elif not hash_before: |
| 1296 status = "A" | 1349 status = "A" |
| 1297 base_content = "" | 1350 base_content = "" |
| 1298 elif not hash_after: | 1351 elif not hash_after: |
| 1299 status = "D" | 1352 status = "D" |
| 1300 else: | 1353 else: |
| 1301 status = "M" | 1354 status = "M" |
| 1302 | 1355 |
| 1303 is_binary = self.IsBinaryData(base_content) | 1356 is_binary = self.IsBinaryData(base_content) |
| 1304 is_image = self.IsImage(filename) | 1357 is_image = self.IsImage(filename) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1316 | 1369 |
| 1317 return (base_content, new_content, is_binary, status) | 1370 return (base_content, new_content, is_binary, status) |
| 1318 | 1371 |
| 1319 | 1372 |
| 1320 class CVSVCS(VersionControlSystem): | 1373 class CVSVCS(VersionControlSystem): |
| 1321 """Implementation of the VersionControlSystem interface for CVS.""" | 1374 """Implementation of the VersionControlSystem interface for CVS.""" |
| 1322 | 1375 |
| 1323 def __init__(self, options): | 1376 def __init__(self, options): |
| 1324 super(CVSVCS, self).__init__(options) | 1377 super(CVSVCS, self).__init__(options) |
| 1325 | 1378 |
| 1379 def GetGUID(self): |
| 1380 """For now we don't know how to get repository ID for CVS""" |
| 1381 return |
| 1382 |
| 1326 def GetOriginalContent_(self, filename): | 1383 def GetOriginalContent_(self, filename): |
| 1327 RunShell(["cvs", "up", filename], silent_ok=True) | 1384 RunShell(["cvs", "up", filename], silent_ok=True) |
| 1328 # TODO need detect file content encoding | 1385 # TODO need detect file content encoding |
| 1329 content = open(filename).read() | 1386 content = open(filename).read() |
| 1330 return content.replace("\r\n", "\n") | 1387 return content.replace("\r\n", "\n") |
| 1331 | 1388 |
| 1332 def GetBaseFile(self, filename): | 1389 def GetBaseFile(self, filename): |
| 1333 base_content = None | 1390 base_content = None |
| 1334 new_content = None | 1391 new_content = None |
| 1335 status = "A" | 1392 status = "A" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 self.repo_dir = os.path.normpath(repo_dir) | 1448 self.repo_dir = os.path.normpath(repo_dir) |
| 1392 # Compute the subdir | 1449 # Compute the subdir |
| 1393 cwd = os.path.normpath(os.getcwd()) | 1450 cwd = os.path.normpath(os.getcwd()) |
| 1394 assert cwd.startswith(self.repo_dir) | 1451 assert cwd.startswith(self.repo_dir) |
| 1395 self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/") | 1452 self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/") |
| 1396 if self.options.revision: | 1453 if self.options.revision: |
| 1397 self.base_rev = self.options.revision | 1454 self.base_rev = self.options.revision |
| 1398 else: | 1455 else: |
| 1399 self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() | 1456 self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() |
| 1400 | 1457 |
| 1458 def GetGUID(self): |
| 1459 # See chapter "Uniquely identifying a repository" |
| 1460 # http://hgbook.red-bean.com/read/customizing-the-output-of-mercurial.html |
| 1461 info = RunShell("hg log -r0 --template {node}".split()) |
| 1462 return info.strip() |
| 1463 |
| 1401 def _GetRelPath(self, filename): | 1464 def _GetRelPath(self, filename): |
| 1402 """Get relative path of a file according to the current directory, | 1465 """Get relative path of a file according to the current directory, |
| 1403 given its logical path in the repo.""" | 1466 given its logical path in the repo.""" |
| 1404 assert filename.startswith(self.subdir), (filename, self.subdir) | 1467 assert filename.startswith(self.subdir), (filename, self.subdir) |
| 1405 return filename[len(self.subdir):].lstrip(r"\/") | 1468 return filename[len(self.subdir):].lstrip(r"\/") |
| 1406 | 1469 |
| 1407 def GenerateDiff(self, extra_args): | 1470 def GenerateDiff(self, extra_args): |
| 1408 cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args | 1471 cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args |
| 1409 data = RunShell(cmd, silent_ok=True) | 1472 data = RunShell(cmd, silent_ok=True) |
| 1410 svndiff = [] | 1473 svndiff = [] |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 if not options.message: | 1578 if not options.message: |
| 1516 description = self.RunPerforceCommand(["describe", self.p4_changelist], | 1579 description = self.RunPerforceCommand(["describe", self.p4_changelist], |
| 1517 marshal_output=True) | 1580 marshal_output=True) |
| 1518 if description and "desc" in description: | 1581 if description and "desc" in description: |
| 1519 # Rietveld doesn't support multi-line descriptions | 1582 # Rietveld doesn't support multi-line descriptions |
| 1520 raw_message = description["desc"].strip() | 1583 raw_message = description["desc"].strip() |
| 1521 lines = raw_message.splitlines() | 1584 lines = raw_message.splitlines() |
| 1522 if len(lines): | 1585 if len(lines): |
| 1523 options.message = lines[0] | 1586 options.message = lines[0] |
| 1524 | 1587 |
| 1588 def GetGUID(self): |
| 1589 """For now we don't know how to get repository ID for Perforce""" |
| 1590 return |
| 1591 |
| 1525 def RunPerforceCommandWithReturnCode(self, extra_args, marshal_output=False, | 1592 def RunPerforceCommandWithReturnCode(self, extra_args, marshal_output=False, |
| 1526 universal_newlines=True): | 1593 universal_newlines=True): |
| 1527 args = ["p4"] | 1594 args = ["p4"] |
| 1528 if marshal_output: | 1595 if marshal_output: |
| 1529 # -G makes perforce format its output as marshalled python objects | 1596 # -G makes perforce format its output as marshalled python objects |
| 1530 args.extend(["-G"]) | 1597 args.extend(["-G"]) |
| 1531 if self.p4_port: | 1598 if self.p4_port: |
| 1532 args.extend(["-p", self.p4_port]) | 1599 args.extend(["-p", self.p4_port]) |
| 1533 if self.p4_client: | 1600 if self.p4_client: |
| 1534 args.extend(["-c", self.p4_client]) | 1601 args.extend(["-c", self.p4_client]) |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2101 argv: Command line arguments. | 2168 argv: Command line arguments. |
| 2102 data: Diff contents. If None (default) the diff is generated by | 2169 data: Diff contents. If None (default) the diff is generated by |
| 2103 the VersionControlSystem implementation returned by GuessVCS(). | 2170 the VersionControlSystem implementation returned by GuessVCS(). |
| 2104 | 2171 |
| 2105 Returns: | 2172 Returns: |
| 2106 A 2-tuple (issue id, patchset id). | 2173 A 2-tuple (issue id, patchset id). |
| 2107 The patchset id is None if the base files are not uploaded by this | 2174 The patchset id is None if the base files are not uploaded by this |
| 2108 script (applies only to SVN checkouts). | 2175 script (applies only to SVN checkouts). |
| 2109 """ | 2176 """ |
| 2110 options, args = parser.parse_args(argv[1:]) | 2177 options, args = parser.parse_args(argv[1:]) |
| 2178 if options.help: |
| 2179 if options.verbose < 2: |
| 2180 # hide Perforce options |
| 2181 parser.epilog = "Use '--help -v' to show additional Perforce options." |
| 2182 parser.option_groups.remove(parser.get_option_group('--p4_port')) |
| 2183 parser.print_help() |
| 2184 sys.exit(0) |
| 2185 |
| 2111 global verbosity | 2186 global verbosity |
| 2112 verbosity = options.verbose | 2187 verbosity = options.verbose |
| 2113 if verbosity >= 3: | 2188 if verbosity >= 3: |
| 2114 logging.getLogger().setLevel(logging.DEBUG) | 2189 logging.getLogger().setLevel(logging.DEBUG) |
| 2115 elif verbosity >= 2: | 2190 elif verbosity >= 2: |
| 2116 logging.getLogger().setLevel(logging.INFO) | 2191 logging.getLogger().setLevel(logging.INFO) |
| 2117 | 2192 |
| 2118 vcs = GuessVCS(options) | 2193 vcs = GuessVCS(options) |
| 2119 | 2194 |
| 2120 base = options.base_url | 2195 base = options.base_url |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2150 prompt = "New issue subject: " | 2225 prompt = "New issue subject: " |
| 2151 message = options.message or raw_input(prompt).strip() | 2226 message = options.message or raw_input(prompt).strip() |
| 2152 if not message: | 2227 if not message: |
| 2153 ErrorExit("A non-empty message is required") | 2228 ErrorExit("A non-empty message is required") |
| 2154 rpc_server = GetRpcServer(options.server, | 2229 rpc_server = GetRpcServer(options.server, |
| 2155 options.email, | 2230 options.email, |
| 2156 options.host, | 2231 options.host, |
| 2157 options.save_cookies, | 2232 options.save_cookies, |
| 2158 options.account_type) | 2233 options.account_type) |
| 2159 form_fields = [("subject", message)] | 2234 form_fields = [("subject", message)] |
| 2235 |
| 2236 repo_guid = vcs.GetGUID() |
| 2237 if repo_guid: |
| 2238 form_fields.append(("repo_guid", repo_guid)) |
| 2160 if base: | 2239 if base: |
| 2161 b = urlparse.urlparse(base) | 2240 b = urlparse.urlparse(base) |
| 2162 username, netloc = urllib.splituser(b.netloc) | 2241 username, netloc = urllib.splituser(b.netloc) |
| 2163 if username: | 2242 if username: |
| 2164 logging.info("Removed username from base URL") | 2243 logging.info("Removed username from base URL") |
| 2165 base = urlparse.urlunparse((b.scheme, netloc, b.path, b.params, | 2244 base = urlparse.urlunparse((b.scheme, netloc, b.path, b.params, |
| 2166 b.query, b.fragment)) | 2245 b.query, b.fragment)) |
| 2167 form_fields.append(("base", base)) | 2246 form_fields.append(("base", base)) |
| 2168 if options.issue: | 2247 if options.issue: |
| 2169 form_fields.append(("issue", str(options.issue))) | 2248 form_fields.append(("issue", str(options.issue))) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 os.environ['LC_ALL'] = 'C' | 2335 os.environ['LC_ALL'] = 'C' |
| 2257 RealMain(sys.argv) | 2336 RealMain(sys.argv) |
| 2258 except KeyboardInterrupt: | 2337 except KeyboardInterrupt: |
| 2259 print | 2338 print |
| 2260 StatusUpdate("Interrupted.") | 2339 StatusUpdate("Interrupted.") |
| 2261 sys.exit(1) | 2340 sys.exit(1) |
| 2262 | 2341 |
| 2263 | 2342 |
| 2264 if __name__ == "__main__": | 2343 if __name__ == "__main__": |
| 2265 main() | 2344 main() |
| OLD | NEW |