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

Side by Side Diff: gcl.py

Issue 391052: Group SCM-specific functions in classes to simplify generalization of the interface. (Closed)
Patch Set: One more fix Created 11 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
« no previous file with comments | « no previous file | gclient.py » ('j') | gclient.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Wrapper script around Rietveld's upload.py that groups files into 6 """Wrapper script around Rietveld's upload.py that groups files into
7 changelists.""" 7 changelists."""
8 8
9 import getpass 9 import getpass
10 import os 10 import os
11 import random 11 import random
12 import re 12 import re
13 import shutil 13 import shutil
14 import string 14 import string
15 import subprocess 15 import subprocess
16 import sys 16 import sys
17 import tempfile 17 import tempfile
18 import upload 18 import upload
19 import urllib2 19 import urllib2
20 20
21 # gcl now depends on gclient. 21 # gcl now depends on gclient.
22 import gclient_scm 22 from scm import SVN
23 import gclient_utils 23 import gclient_utils
24 24
25 __version__ = '1.1.1' 25 __version__ = '1.1.2'
26 26
27 27
28 CODEREVIEW_SETTINGS = { 28 CODEREVIEW_SETTINGS = {
29 # Default values. 29 # Default values.
30 "CODE_REVIEW_SERVER": "codereview.chromium.org", 30 "CODE_REVIEW_SERVER": "codereview.chromium.org",
31 "CC_LIST": "chromium-reviews@googlegroups.com", 31 "CC_LIST": "chromium-reviews@googlegroups.com",
32 "VIEW_VC": "http://src.chromium.org/viewvc/chrome?view=rev&revision=", 32 "VIEW_VC": "http://src.chromium.org/viewvc/chrome?view=rev&revision=",
33 } 33 }
34 34
35 # globals that store the root of the current repository and the directory where 35 # globals that store the root of the current repository and the directory where
36 # we store information about changelists. 36 # we store information about changelists.
37 REPOSITORY_ROOT = "" 37 REPOSITORY_ROOT = ""
38 38
39 # Filename where we store repository specific information for gcl. 39 # Filename where we store repository specific information for gcl.
40 CODEREVIEW_SETTINGS_FILE = "codereview.settings" 40 CODEREVIEW_SETTINGS_FILE = "codereview.settings"
41 41
42 # Warning message when the change appears to be missing tests. 42 # Warning message when the change appears to be missing tests.
43 MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!" 43 MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!"
44 44
45 # Global cache of files cached in GetCacheDir(). 45 # Global cache of files cached in GetCacheDir().
46 FILES_CACHE = {} 46 FILES_CACHE = {}
47 47
48 48
49 ### SVN Functions
50
51 def IsSVNMoved(filename):
M-A Ruel 2009/11/13 21:41:07 These 2 functions are moved to scm.py near the bot
52 """Determine if a file has been added through svn mv"""
53 info = gclient_scm.CaptureSVNInfo(filename)
54 return (info.get('Copied From URL') and
55 info.get('Copied From Rev') and
56 info.get('Schedule') == 'add')
57
58
59 def GetSVNFileProperty(file, property_name):
60 """Returns the value of an SVN property for the given file.
61
62 Args:
63 file: The file to check
64 property_name: The name of the SVN property, e.g. "svn:mime-type"
65
66 Returns:
67 The value of the property, which will be the empty string if the property
68 is not set on the file. If the file is not under version control, the
69 empty string is also returned.
70 """
71 output = RunShell(["svn", "propget", property_name, file])
72 if (output.startswith("svn: ") and
73 output.endswith("is not under version control")):
74 return ""
75 else:
76 return output
77
78
79 def UnknownFiles(extra_args): 49 def UnknownFiles(extra_args):
80 """Runs svn status and prints unknown files. 50 """Runs svn status and prints unknown files.
81 51
82 Any args in |extra_args| are passed to the tool to support giving alternate 52 Any args in |extra_args| are passed to the tool to support giving alternate
83 code locations. 53 code locations.
84 """ 54 """
85 return [item[1] for item in gclient_scm.CaptureSVNStatus(extra_args) 55 return [item[1] for item in SVN.CaptureStatus(extra_args)
86 if item[0][0] == '?'] 56 if item[0][0] == '?']
87 57
88 58
89 def GetRepositoryRoot(): 59 def GetRepositoryRoot():
90 """Returns the top level directory of the current repository. 60 """Returns the top level directory of the current repository.
91 61
92 The directory is returned as an absolute path. 62 The directory is returned as an absolute path.
93 """ 63 """
94 global REPOSITORY_ROOT 64 global REPOSITORY_ROOT
95 if not REPOSITORY_ROOT: 65 if not REPOSITORY_ROOT:
96 infos = gclient_scm.CaptureSVNInfo(os.getcwd(), print_error=False) 66 infos = SVN.CaptureInfo(os.getcwd(), print_error=False)
97 cur_dir_repo_root = infos.get("Repository Root") 67 cur_dir_repo_root = infos.get("Repository Root")
98 if not cur_dir_repo_root: 68 if not cur_dir_repo_root:
99 raise gclient_utils.Error("gcl run outside of repository") 69 raise gclient_utils.Error("gcl run outside of repository")
100 70
101 REPOSITORY_ROOT = os.getcwd() 71 REPOSITORY_ROOT = os.getcwd()
102 while True: 72 while True:
103 parent = os.path.dirname(REPOSITORY_ROOT) 73 parent = os.path.dirname(REPOSITORY_ROOT)
104 if (gclient_scm.CaptureSVNInfo(parent, print_error=False).get( 74 if (SVN.CaptureInfo(parent, print_error=False).get(
105 "Repository Root") != cur_dir_repo_root): 75 "Repository Root") != cur_dir_repo_root):
106 break 76 break
107 REPOSITORY_ROOT = parent 77 REPOSITORY_ROOT = parent
108 return REPOSITORY_ROOT 78 return REPOSITORY_ROOT
109 79
110 80
111 def GetInfoDir(): 81 def GetInfoDir():
112 """Returns the directory where gcl info files are stored.""" 82 """Returns the directory where gcl info files are stored."""
113 return os.path.join(GetRepositoryRoot(), '.svn', 'gcl_info') 83 return os.path.join(GetRepositoryRoot(), '.svn', 'gcl_info')
114 84
(...skipping 24 matching lines...) Expand all
139 FILES_CACHE[filename] = None 109 FILES_CACHE[filename] = None
140 # First we check if we have a cached version. 110 # First we check if we have a cached version.
141 try: 111 try:
142 cached_file = os.path.join(GetCacheDir(), filename) 112 cached_file = os.path.join(GetCacheDir(), filename)
143 except gclient_utils.Error: 113 except gclient_utils.Error:
144 return None 114 return None
145 if (not os.path.exists(cached_file) or 115 if (not os.path.exists(cached_file) or
146 os.stat(cached_file).st_mtime > max_age): 116 os.stat(cached_file).st_mtime > max_age):
147 local_dir = os.path.dirname(os.path.abspath(filename)) 117 local_dir = os.path.dirname(os.path.abspath(filename))
148 local_base = os.path.basename(filename) 118 local_base = os.path.basename(filename)
149 dir_info = gclient_scm.CaptureSVNInfo(".") 119 dir_info = SVN.CaptureInfo(".")
150 repo_root = dir_info["Repository Root"] 120 repo_root = dir_info["Repository Root"]
151 if use_root: 121 if use_root:
152 url_path = repo_root 122 url_path = repo_root
153 else: 123 else:
154 url_path = dir_info["URL"] 124 url_path = dir_info["URL"]
155 content = "" 125 content = ""
156 while True: 126 while True:
157 # First, look for a locally modified version of the file if we can. 127 # First, look for a locally modified version of the file if we can.
158 r = "" 128 r = ""
159 if not use_root: 129 if not use_root:
160 local_path = os.path.join(local_dir, local_base) 130 local_path = os.path.join(local_dir, local_base)
161 r = gclient_scm.CaptureSVNStatus((local_path,)) 131 r = SVN.CaptureStatus((local_path,))
162 rc = -1 132 rc = -1
163 if r: 133 if r:
164 status = r[0][0] 134 status = r[0][0]
165 rc = 0 135 rc = 0
166 if not rc and status[0] in ('A','M'): 136 if not rc and status[0] in ('A','M'):
167 content = ReadFile(local_path) 137 content = ReadFile(local_path)
168 rc = 0 138 rc = 0
169 else: 139 else:
170 # Look in the repository if we didn't find something local. 140 # Look in the repository if we didn't find something local.
171 svn_path = url_path + "/" + filename 141 svn_path = url_path + "/" + filename
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 files = [] 441 files = []
472 for line in split_data[1].splitlines(): 442 for line in split_data[1].splitlines():
473 status = line[:7] 443 status = line[:7]
474 filename = line[7:] 444 filename = line[7:]
475 files.append((status, filename)) 445 files.append((status, filename))
476 description = split_data[2] 446 description = split_data[2]
477 save = False 447 save = False
478 if update_status: 448 if update_status:
479 for item in files: 449 for item in files:
480 filename = os.path.join(local_root, item[1]) 450 filename = os.path.join(local_root, item[1])
481 status_result = gclient_scm.CaptureSVNStatus(filename) 451 status_result = SVN.CaptureStatus(filename)
482 if not status_result or not status_result[0][0]: 452 if not status_result or not status_result[0][0]:
483 # File has been reverted. 453 # File has been reverted.
484 save = True 454 save = True
485 files.remove(item) 455 files.remove(item)
486 continue 456 continue
487 status = status_result[0][0] 457 status = status_result[0][0]
488 if status != item[0]: 458 if status != item[0]:
489 save = True 459 save = True
490 files[files.index(item)] = (status, item[1]) 460 files[files.index(item)] = (status, item[1])
491 change_info = ChangeInfo(changename, issue, patchset, description, files, 461 change_info = ChangeInfo(changename, issue, patchset, description, files,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 525
556 # Get a list of all files in changelists. 526 # Get a list of all files in changelists.
557 files_in_cl = {} 527 files_in_cl = {}
558 for cl in GetCLs(): 528 for cl in GetCLs():
559 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), 529 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(),
560 fail_on_not_found=True, update_status=False) 530 fail_on_not_found=True, update_status=False)
561 for status, filename in change_info.GetFiles(): 531 for status, filename in change_info.GetFiles():
562 files_in_cl[filename] = change_info.name 532 files_in_cl[filename] = change_info.name
563 533
564 # Get all the modified files. 534 # Get all the modified files.
565 status_result = gclient_scm.CaptureSVNStatus(None) 535 status_result = SVN.CaptureStatus(None)
566 for line in status_result: 536 for line in status_result:
567 status = line[0] 537 status = line[0]
568 filename = line[1] 538 filename = line[1]
569 if status[0] == "?": 539 if status[0] == "?":
570 continue 540 continue
571 if dir_prefix: 541 if dir_prefix:
572 filename = os.path.join(dir_prefix, filename) 542 filename = os.path.join(dir_prefix, filename)
573 change_list_name = "" 543 change_list_name = ""
574 if filename in files_in_cl: 544 if filename in files_in_cl:
575 change_list_name = files_in_cl[filename] 545 change_list_name = files_in_cl[filename]
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 previous_cwd = os.getcwd() 714 previous_cwd = os.getcwd()
745 if root is None: 715 if root is None:
746 os.chdir(GetRepositoryRoot()) 716 os.chdir(GetRepositoryRoot())
747 else: 717 else:
748 os.chdir(root) 718 os.chdir(root)
749 719
750 diff = [] 720 diff = []
751 for filename in files: 721 for filename in files:
752 # Use svn info output instead of os.path.isdir because the latter fails 722 # Use svn info output instead of os.path.isdir because the latter fails
753 # when the file is deleted. 723 # when the file is deleted.
754 if gclient_scm.CaptureSVNInfo(filename).get("Node Kind") in ("dir", 724 if SVN.CaptureInfo(file).get('Node Kind') == 'directory':
755 "directory"):
756 continue 725 continue
757 # If the user specified a custom diff command in their svn config file, 726 # If the user specified a custom diff command in their svn config file,
758 # then it'll be used when we do svn diff, which we don't want to happen 727 # then it'll be used when we do svn diff, which we don't want to happen
759 # since we want the unified diff. Using --diff-cmd=diff doesn't always 728 # since we want the unified diff. Using --diff-cmd=diff doesn't always
760 # work, since they can have another diff executable in their path that 729 # work, since they can have another diff executable in their path that
761 # gives different line endings. So we use a bogus temp directory as the 730 # gives different line endings. So we use a bogus temp directory as the
762 # config directory, which gets around these problems. 731 # config directory, which gets around these problems.
763 if sys.platform.startswith("win"): 732 if sys.platform.startswith("win"):
764 parent_dir = tempfile.gettempdir() 733 parent_dir = tempfile.gettempdir()
765 else: 734 else:
766 parent_dir = sys.path[0] # tempdir is not secure. 735 parent_dir = sys.path[0] # tempdir is not secure.
767 bogus_dir = os.path.join(parent_dir, "temp_svn_config") 736 bogus_dir = os.path.join(parent_dir, "temp_svn_config")
768 if not os.path.exists(bogus_dir): 737 if not os.path.exists(bogus_dir):
769 os.mkdir(bogus_dir) 738 os.mkdir(bogus_dir)
770 output = RunShell(["svn", "diff", "--config-dir", bogus_dir, filename]) 739 output = RunShell(["svn", "diff", "--config-dir", bogus_dir, filename])
771 if output: 740 if output:
772 diff.append(output) 741 diff.append(output)
773 elif IsSVNMoved(filename): 742 elif SVN.IsMoved(filename):
774 # svn diff on a mv/cp'd file outputs nothing. 743 # svn diff on a mv/cp'd file outputs nothing.
775 # We put in an empty Index entry so upload.py knows about them. 744 # We put in an empty Index entry so upload.py knows about them.
776 diff.append("\nIndex: %s\n" % filename) 745 diff.append("\nIndex: %s\n" % filename)
777 else: 746 else:
778 # The file is not modified anymore. It should be removed from the set. 747 # The file is not modified anymore. It should be removed from the set.
779 pass 748 pass
780 os.chdir(previous_cwd) 749 os.chdir(previous_cwd)
781 return "".join(diff) 750 return "".join(diff)
782 751
783 752
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 change_info.description += "\nCommitted: " + viewvc_url + revision 958 change_info.description += "\nCommitted: " + viewvc_url + revision
990 change_info.CloseIssue() 959 change_info.CloseIssue()
991 os.chdir(previous_cwd) 960 os.chdir(previous_cwd)
992 961
993 962
994 def Change(change_info, args): 963 def Change(change_info, args):
995 """Creates/edits a changelist.""" 964 """Creates/edits a changelist."""
996 silent = FilterFlag(args, "--silent") 965 silent = FilterFlag(args, "--silent")
997 966
998 # Verify the user is running the change command from a read-write checkout. 967 # Verify the user is running the change command from a read-write checkout.
999 svn_info = gclient_scm.CaptureSVNInfo('.') 968 svn_info = SVN.CaptureInfo('.')
1000 if not svn_info: 969 if not svn_info:
1001 ErrorExit("Current checkout is unversioned. Please retry with a versioned " 970 ErrorExit("Current checkout is unversioned. Please retry with a versioned "
1002 "directory.") 971 "directory.")
1003 972
1004 if (len(args) == 1): 973 if (len(args) == 1):
1005 filename = args[0] 974 filename = args[0]
1006 f = open(filename, 'rU') 975 f = open(filename, 'rU')
1007 override_description = f.read() 976 override_description = f.read()
1008 f.close() 977 f.close()
1009 else: 978 else:
1010 override_description = None 979 override_description = None
1011 980
1012 if change_info.issue: 981 if change_info.issue:
1013 try: 982 try:
1014 description = GetIssueDescription(change_info.issue) 983 description = GetIssueDescription(change_info.issue)
1015 except urllib2.HTTPError, err: 984 except urllib2.HTTPError, err:
1016 if err.code == 404: 985 if err.code == 404:
1017 # The user deleted the issue in Rietveld, so forget the old issue id. 986 # The user deleted the issue in Rietveld, so forget the old issue id.
1018 description = change_info.description 987 description = change_info.description
1019 change_info.issue = 0 988 change_info.issue = 0
1020 change_info.Save() 989 change_info.Save()
1021 else: 990 else:
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 return 0 1263 return 0
1295 args =["svn", command] 1264 args =["svn", command]
1296 root = GetRepositoryRoot() 1265 root = GetRepositoryRoot()
1297 args.extend([os.path.join(root, x) for x in change_info.GetFileNames()]) 1266 args.extend([os.path.join(root, x) for x in change_info.GetFileNames()])
1298 RunShell(args, True) 1267 RunShell(args, True)
1299 return 0 1268 return 0
1300 1269
1301 1270
1302 if __name__ == "__main__": 1271 if __name__ == "__main__":
1303 sys.exit(main()) 1272 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | gclient.py » ('j') | gclient.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698