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

Side by Side Diff: third_party/upload.py

Issue 5172007: Update upload.py to r590. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/third_party
Patch Set: Created 10 years, 1 month 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 # 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 #
11 # Unless required by applicable law or agreed to in writing, software 11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, 12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and 14 # See the License for the specific language governing permissions and
15 # limitations under the License. 15 # limitations under the License.
16 16
17 """Tool for uploading diffs from a version control system to the codereview app. 17 """Tool for uploading diffs from a version control system to the codereview app.
18 18
19 Usage summary: upload.py [options] [-- diff_options] 19 Usage summary: upload.py [options] [-- diff_options] [path...]
20 20
21 Diff options are passed to the diff command of the underlying system. 21 Diff options are passed to the diff command of the underlying system.
22 22
23 Supported version control systems: 23 Supported version control systems:
24 Git 24 Git
25 Mercurial 25 Mercurial
26 Subversion 26 Subversion
27 27
28 It is important for Git/Mercurial users to specify a tree/node/branch to diff 28 It is important for Git/Mercurial users to specify a tree/node/branch to diff
29 against by using the '--rev' option. 29 against by using the '--rev' option.
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 os.close(fd) 440 os.close(fd)
441 # Always chmod the cookie file 441 # Always chmod the cookie file
442 os.chmod(self.cookie_file, 0600) 442 os.chmod(self.cookie_file, 0600)
443 else: 443 else:
444 # Don't save cookies across runs of update.py. 444 # Don't save cookies across runs of update.py.
445 self.cookie_jar = cookielib.CookieJar() 445 self.cookie_jar = cookielib.CookieJar()
446 opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) 446 opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
447 return opener 447 return opener
448 448
449 449
450 parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]") 450 parser = optparse.OptionParser(
451 usage="%prog [options] [-- diff_options] [path...]")
451 parser.add_option("-y", "--assume_yes", action="store_true", 452 parser.add_option("-y", "--assume_yes", action="store_true",
452 dest="assume_yes", default=False, 453 dest="assume_yes", default=False,
453 help="Assume that the answer to yes/no questions is 'yes'.") 454 help="Assume that the answer to yes/no questions is 'yes'.")
454 # Logging 455 # Logging
455 group = parser.add_option_group("Logging options") 456 group = parser.add_option_group("Logging options")
456 group.add_option("-q", "--quiet", action="store_const", const=0, 457 group.add_option("-q", "--quiet", action="store_const", const=0,
457 dest="verbose", help="Print errors only.") 458 dest="verbose", help="Print errors only.")
458 group.add_option("-v", "--verbose", action="store_const", const=2, 459 group.add_option("-v", "--verbose", action="store_const", const=2,
459 dest="verbose", default=1, 460 dest="verbose", default=1,
460 help="Print info level logs (default).") 461 help="Print info level logs.")
461 group.add_option("--noisy", action="store_const", const=3, 462 group.add_option("--noisy", action="store_const", const=3,
462 dest="verbose", help="Print all logs.") 463 dest="verbose", help="Print all logs.")
463 # Review server 464 # Review server
464 group = parser.add_option_group("Review server options") 465 group = parser.add_option_group("Review server options")
465 group.add_option("-s", "--server", action="store", dest="server", 466 group.add_option("-s", "--server", action="store", dest="server",
466 default=DEFAULT_REVIEW_SERVER, 467 default=DEFAULT_REVIEW_SERVER,
467 metavar="SERVER", 468 metavar="SERVER",
468 help=("The server to upload to. The format is host[:port]. " 469 help=("The server to upload to. The format is host[:port]. "
469 "Defaults to '%default'.")) 470 "Defaults to '%default'."))
470 group.add_option("-e", "--email", action="store", dest="email", 471 group.add_option("-e", "--email", action="store", dest="email",
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE. 549 or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE.
549 550
550 Returns: 551 Returns:
551 A new AbstractRpcServer, on which RPC calls can be made. 552 A new AbstractRpcServer, on which RPC calls can be made.
552 """ 553 """
553 554
554 rpc_server_class = HttpRpcServer 555 rpc_server_class = HttpRpcServer
555 556
556 # If this is the dev_appserver, use fake authentication. 557 # If this is the dev_appserver, use fake authentication.
557 host = (host_override or server).lower() 558 host = (host_override or server).lower()
558 if host == "localhost" or host.startswith("localhost:"): 559 if re.match(r'(http://)?localhost([:/]|$)', host):
559 if email is None: 560 if email is None:
560 email = "test@example.com" 561 email = "test@example.com"
561 logging.info("Using debug user %s. Override with --email" % email) 562 logging.info("Using debug user %s. Override with --email" % email)
562 server = rpc_server_class( 563 server = rpc_server_class(
563 server, 564 server,
564 lambda: (email, "password"), 565 lambda: (email, "password"),
565 host_override=host_override, 566 host_override=host_override,
566 extra_headers={"Cookie": 567 extra_headers={"Cookie":
567 'dev_appserver_login="%s:False"' % email}, 568 'dev_appserver_login="%s:False"' % email},
568 save_cookies=save_cookies, 569 save_cookies=save_cookies,
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 # Base URL is required to fetch files deleted in an older revision. 861 # Base URL is required to fetch files deleted in an older revision.
861 # Result is cached to not guess it over and over again in GetBaseFile(). 862 # Result is cached to not guess it over and over again in GetBaseFile().
862 required = self.options.download_base or self.options.revision is not None 863 required = self.options.download_base or self.options.revision is not None
863 self.svn_base = self._GuessBase(required) 864 self.svn_base = self._GuessBase(required)
864 865
865 def GuessBase(self, required): 866 def GuessBase(self, required):
866 """Wrapper for _GuessBase.""" 867 """Wrapper for _GuessBase."""
867 return self.svn_base 868 return self.svn_base
868 869
869 def _GuessBase(self, required): 870 def _GuessBase(self, required):
870 """Returns the SVN base URL. 871 """Returns base URL for current diff.
871 872
872 Args: 873 Args:
873 required: If true, exits if the url can't be guessed, otherwise None is 874 required: If true, exits if the url can't be guessed, otherwise None is
874 returned. 875 returned.
875 """ 876 """
876 info = RunShell(["svn", "info"]) 877 info = RunShell(["svn", "info"])
877 for line in info.splitlines(): 878 for line in info.splitlines():
878 words = line.split() 879 if line.startswith("URL: "):
879 if len(words) == 2 and words[0] == "URL:": 880 url = line.split()[1]
880 url = words[1]
881 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) 881 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
882 username, netloc = urllib.splituser(netloc) 882 username, netloc = urllib.splituser(netloc)
883 if username: 883 if username:
884 logging.info("Removed username from base URL") 884 logging.info("Removed username from base URL")
885 if netloc.endswith("svn.python.org"): 885 guess = ""
886 if netloc == "svn.python.org": 886 if netloc == "svn.python.org" and scheme == "svn+ssh":
887 if path.startswith("/projects/"): 887 path = "projects" + path
888 path = path[9:] 888 scheme = "http"
889 elif netloc != "pythondev@svn.python.org": 889 guess = "Python "
890 ErrorExit("Unrecognized Python URL: %s" % url)
891 base = "http://svn.python.org/view/*checkout*%s/" % path
892 logging.info("Guessed Python base = %s", base)
893 elif netloc.endswith("svn.collab.net"):
894 if path.startswith("/repos/"):
895 path = path[6:]
896 base = "http://svn.collab.net/viewvc/*checkout*%s/" % path
897 logging.info("Guessed CollabNet base = %s", base)
898 elif netloc.endswith(".googlecode.com"): 890 elif netloc.endswith(".googlecode.com"):
899 path = path + "/" 891 scheme = "http"
900 base = urlparse.urlunparse(("http", netloc, path, params, 892 guess = "Google Code "
901 query, fragment)) 893 path = path + "/"
902 logging.info("Guessed Google Code base = %s", base) 894 base = urlparse.urlunparse((scheme, netloc, path, params,
903 else: 895 query, fragment))
904 path = path + "/" 896 logging.info("Guessed %sbase = %s", guess, base)
905 base = urlparse.urlunparse((scheme, netloc, path, params,
906 query, fragment))
907 logging.info("Guessed base = %s", base)
908 return base 897 return base
909 if required: 898 if required:
910 ErrorExit("Can't find URL in output from svn info") 899 ErrorExit("Can't find URL in output from svn info")
911 return None 900 return None
912 901
913 def GenerateDiff(self, args): 902 def GenerateDiff(self, args):
914 cmd = ["svn", "diff"] 903 cmd = ["svn", "diff"]
915 if self.options.revision: 904 if self.options.revision:
916 cmd += ["-r", self.options.revision] 905 cmd += ["-r", self.options.revision]
917 cmd.extend(args) 906 cmd.extend(args)
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 if not filecount: 1167 if not filecount:
1179 ErrorExit("No valid patches found in output from git diff") 1168 ErrorExit("No valid patches found in output from git diff")
1180 # Add auto property for the last seen file. 1169 # Add auto property for the last seen file.
1181 assert filename is not None 1170 assert filename is not None
1182 AddSubversionPropertyChange(filename) 1171 AddSubversionPropertyChange(filename)
1183 return "".join(svndiff) 1172 return "".join(svndiff)
1184 1173
1185 def GenerateDiff(self, extra_args): 1174 def GenerateDiff(self, extra_args):
1186 extra_args = extra_args[:] 1175 extra_args = extra_args[:]
1187 if self.options.revision: 1176 if self.options.revision:
1188 extra_args = [self.options.revision] + extra_args 1177 if ":" in self.options.revision:
1178 extra_args = self.options.revision.split(":", 1) + extra_args
1179 else:
1180 extra_args = [self.options.revision] + extra_args
1189 1181
1190 # --no-ext-diff is broken in some versions of Git, so try to work around 1182 # --no-ext-diff is broken in some versions of Git, so try to work around
1191 # this by overriding the environment (but there is still a problem if the 1183 # this by overriding the environment (but there is still a problem if the
1192 # git config key "diff.external" is used). 1184 # git config key "diff.external" is used).
1193 env = os.environ.copy() 1185 env = os.environ.copy()
1194 if 'GIT_EXTERNAL_DIFF' in env: del env['GIT_EXTERNAL_DIFF'] 1186 if 'GIT_EXTERNAL_DIFF' in env: del env['GIT_EXTERNAL_DIFF']
1195 return RunShell(["git", "diff", "--no-ext-diff", "--full-index", "-M"] 1187 return RunShell(["git", "diff", "--no-ext-diff", "--full-index", "-M"]
1196 + extra_args, env=env) 1188 + extra_args, env=env)
1197 1189
1198 def GetUnknownFiles(self): 1190 def GetUnknownFiles(self):
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1260 else: 1252 else:
1261 self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() 1253 self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip()
1262 1254
1263 def _GetRelPath(self, filename): 1255 def _GetRelPath(self, filename):
1264 """Get relative path of a file according to the current directory, 1256 """Get relative path of a file according to the current directory,
1265 given its logical path in the repo.""" 1257 given its logical path in the repo."""
1266 assert filename.startswith(self.subdir), (filename, self.subdir) 1258 assert filename.startswith(self.subdir), (filename, self.subdir)
1267 return filename[len(self.subdir):].lstrip(r"\/") 1259 return filename[len(self.subdir):].lstrip(r"\/")
1268 1260
1269 def GenerateDiff(self, extra_args): 1261 def GenerateDiff(self, extra_args):
1270 # If no file specified, restrict to the current subdir
1271 extra_args = extra_args or ["."]
1272 cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args 1262 cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
1273 data = RunShell(cmd, silent_ok=True) 1263 data = RunShell(cmd, silent_ok=True)
1274 svndiff = [] 1264 svndiff = []
1275 filecount = 0 1265 filecount = 0
1276 for line in data.splitlines(): 1266 for line in data.splitlines():
1277 m = re.match("diff --git a/(\S+) b/(\S+)", line) 1267 m = re.match("diff --git a/(\S+) b/(\S+)", line)
1278 if m: 1268 if m:
1279 # Modify line to make it look like as it comes from svn diff. 1269 # Modify line to make it look like as it comes from svn diff.
1280 # With this modification no changes on the server side are required 1270 # With this modification no changes on the server side are required
1281 # to make upload.py work with Mercurial repos. 1271 # to make upload.py work with Mercurial repos.
(...skipping 30 matching lines...) Expand all
1312 new_content = None 1302 new_content = None
1313 is_binary = False 1303 is_binary = False
1314 oldrelpath = relpath = self._GetRelPath(filename) 1304 oldrelpath = relpath = self._GetRelPath(filename)
1315 # "hg status -C" returns two lines for moved/copied files, one otherwise 1305 # "hg status -C" returns two lines for moved/copied files, one otherwise
1316 out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath]) 1306 out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
1317 out = out.splitlines() 1307 out = out.splitlines()
1318 # HACK: strip error message about missing file/directory if it isn't in 1308 # HACK: strip error message about missing file/directory if it isn't in
1319 # the working copy 1309 # the working copy
1320 if out[0].startswith('%s: ' % relpath): 1310 if out[0].startswith('%s: ' % relpath):
1321 out = out[1:] 1311 out = out[1:]
1322 if len(out) > 1: 1312 status, _ = out[0].split(' ', 1)
1313 if len(out) > 1 and status == "A":
1323 # Moved/copied => considered as modified, use old filename to 1314 # Moved/copied => considered as modified, use old filename to
1324 # retrieve base contents 1315 # retrieve base contents
1325 oldrelpath = out[1].strip() 1316 oldrelpath = out[1].strip()
1326 status = "M" 1317 status = "M"
1327 else:
1328 status, _ = out[0].split(' ', 1)
1329 if ":" in self.base_rev: 1318 if ":" in self.base_rev:
1330 base_rev = self.base_rev.split(":", 1)[0] 1319 base_rev = self.base_rev.split(":", 1)[0]
1331 else: 1320 else:
1332 base_rev = self.base_rev 1321 base_rev = self.base_rev
1333 if status != "A": 1322 if status != "A":
1334 base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], 1323 base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
1335 silent_ok=True) 1324 silent_ok=True)
1336 is_binary = "\0" in base_content # Mercurial's heuristic 1325 is_binary = "\0" in base_content # Mercurial's heuristic
1337 if status != "R": 1326 if status != "R":
1338 new_content = open(relpath, "rb").read() 1327 new_content = open(relpath, "rb").read()
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 """Returns the content of [auto-props] section of Subversion's config file as 1504 """Returns the content of [auto-props] section of Subversion's config file as
1516 a dictionary. 1505 a dictionary.
1517 1506
1518 Returns: 1507 Returns:
1519 A dictionary whose key-value pair corresponds the [auto-props] section's 1508 A dictionary whose key-value pair corresponds the [auto-props] section's
1520 key-value pair. 1509 key-value pair.
1521 In following cases, returns empty dictionary: 1510 In following cases, returns empty dictionary:
1522 - config file doesn't exist, or 1511 - config file doesn't exist, or
1523 - 'enable-auto-props' is not set to 'true-like-value' in [miscellany]. 1512 - 'enable-auto-props' is not set to 'true-like-value' in [miscellany].
1524 """ 1513 """
1525 # Todo(hayato): Windows users might use different path for configuration file. 1514 if os.name == 'nt':
1526 subversion_config = os.path.expanduser("~/.subversion/config") 1515 subversion_config = os.environ.get("APPDATA") + "\\Subversion\\config"
1516 else:
1517 subversion_config = os.path.expanduser("~/.subversion/config")
1527 if not os.path.exists(subversion_config): 1518 if not os.path.exists(subversion_config):
1528 return {} 1519 return {}
1529 config = ConfigParser.ConfigParser() 1520 config = ConfigParser.ConfigParser()
1530 config.read(subversion_config) 1521 config.read(subversion_config)
1531 if (config.has_section("miscellany") and 1522 if (config.has_section("miscellany") and
1532 config.has_option("miscellany", "enable-auto-props") and 1523 config.has_option("miscellany", "enable-auto-props") and
1533 config.getboolean("miscellany", "enable-auto-props") and 1524 config.getboolean("miscellany", "enable-auto-props") and
1534 config.has_section("auto-props")): 1525 config.has_section("auto-props")):
1535 props = {} 1526 props = {}
1536 for file_pattern in config.options("auto-props"): 1527 for file_pattern in config.options("auto-props"):
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 try: 1756 try:
1766 RealMain(sys.argv) 1757 RealMain(sys.argv)
1767 except KeyboardInterrupt: 1758 except KeyboardInterrupt:
1768 print 1759 print
1769 StatusUpdate("Interrupted.") 1760 StatusUpdate("Interrupted.")
1770 sys.exit(1) 1761 sys.exit(1)
1771 1762
1772 1763
1773 if __name__ == "__main__": 1764 if __name__ == "__main__":
1774 main() 1765 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