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

Side by Side Diff: gcl.py

Issue 113290: Deprecate gcl.GetSVNFileInfo() for gclient.CaptureSVNInfo(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: fixed presubmit.py and updated unit tests Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | presubmit.py » ('j') | 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/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 string 13 import string
14 import subprocess 14 import subprocess
15 import sys 15 import sys
16 import tempfile 16 import tempfile
17 import upload 17 import upload
18 import urllib2 18 import urllib2
19 import xml.dom.minidom 19 import xml.dom.minidom
20 20
21 # gcl now depends on gclient.
22 import gclient
21 23
22 __version__ = '1.0' 24 __version__ = '1.0'
23 25
24 26
25 CODEREVIEW_SETTINGS = { 27 CODEREVIEW_SETTINGS = {
26 # Default values. 28 # Default values.
27 "CODE_REVIEW_SERVER": "codereview.chromium.org", 29 "CODE_REVIEW_SERVER": "codereview.chromium.org",
28 "CC_LIST": "chromium-reviews@googlegroups.com", 30 "CC_LIST": "chromium-reviews@googlegroups.com",
29 "VIEW_VC": "http://src.chromium.org/viewvc/chrome?view=rev&revision=", 31 "VIEW_VC": "http://src.chromium.org/viewvc/chrome?view=rev&revision=",
30 } 32 }
31 33
32 # globals that store the root of the current repository and the directory where 34 # globals that store the root of the current repository and the directory where
33 # we store information about changelists. 35 # we store information about changelists.
34 repository_root = "" 36 repository_root = ""
35 gcl_info_dir = "" 37 gcl_info_dir = ""
36 38
37 # Filename where we store repository specific information for gcl. 39 # Filename where we store repository specific information for gcl.
38 CODEREVIEW_SETTINGS_FILE = "codereview.settings" 40 CODEREVIEW_SETTINGS_FILE = "codereview.settings"
39 41
40 # Warning message when the change appears to be missing tests. 42 # Warning message when the change appears to be missing tests.
41 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!"
42 44
43 # Caches whether we read the codereview.settings file yet or not. 45 # Caches whether we read the codereview.settings file yet or not.
44 read_gcl_info = False 46 read_gcl_info = False
45 47
46 48
47 ### Simplified XML processing functions.
48
49 def ParseXML(output):
50 try:
51 return xml.dom.minidom.parseString(output)
52 except xml.parsers.expat.ExpatError:
53 return None
54
55 def GetNamedNodeText(node, node_name):
56 child_nodes = node.getElementsByTagName(node_name)
57 if not child_nodes:
58 return None
59 assert len(child_nodes) == 1 and child_nodes[0].childNodes.length == 1
60 return child_nodes[0].firstChild.nodeValue
61
62
63 def GetNodeNamedAttributeText(node, node_name, attribute_name):
64 child_nodes = node.getElementsByTagName(node_name)
65 if not child_nodes:
66 return None
67 assert len(child_nodes) == 1
68 return child_nodes[0].getAttribute(attribute_name)
69
70
71 ### SVN Functions 49 ### SVN Functions
72 50
73 def IsSVNMoved(filename): 51 def IsSVNMoved(filename):
74 """Determine if a file has been added through svn mv""" 52 """Determine if a file has been added through svn mv"""
75 info = GetSVNFileInfo(filename) 53 info = gclient.CaptureSVNInfo(filename)
76 return (info.get('Copied From URL') and 54 return (info.get('Copied From URL') and
77 info.get('Copied From Rev') and 55 info.get('Copied From Rev') and
78 info.get('Schedule') == 'add') 56 info.get('Schedule') == 'add')
79 57
80 58
81 def GetSVNFileInfo(file):
82 """Returns a dictionary from the svn info output for the given file."""
83 output = RunShell(["svn", "info", "--xml", file])
84 dom = ParseXML(output)
85 result = {}
86 if dom:
87 # /info/entry/
88 # url
89 # reposityory/(root|uuid)
90 # wc-info/(schedule|depth)
91 # commit/(author|date)
92 result['Node Kind'] = GetNodeNamedAttributeText(dom, 'entry', 'kind')
93 result['Repository Root'] = GetNamedNodeText(dom, 'root')
94 result['Schedule'] = GetNamedNodeText(dom, 'schedule')
95 result['URL'] = GetNamedNodeText(dom, 'url')
96 result['Path'] = GetNodeNamedAttributeText(dom, 'entry', 'path')
97 result['Copied From URL'] = GetNamedNodeText(dom, 'copy-from-url')
98 result['Copied From Rev'] = GetNamedNodeText(dom, 'copy-from-rev')
99 return result
100
101
102 def GetSVNFileProperty(file, property_name): 59 def GetSVNFileProperty(file, property_name):
103 """Returns the value of an SVN property for the given file. 60 """Returns the value of an SVN property for the given file.
104 61
105 Args: 62 Args:
106 file: The file to check 63 file: The file to check
107 property_name: The name of the SVN property, e.g. "svn:mime-type" 64 property_name: The name of the SVN property, e.g. "svn:mime-type"
108 65
109 Returns: 66 Returns:
110 The value of the property, which will be the empty string if the property 67 The value of the property, which will be the empty string if the property
111 is not set on the file. If the file is not under version control, the 68 is not set on the file. If the file is not under version control, the
(...skipping 26 matching lines...) Expand all
138 'deleted': 'D', 95 'deleted': 'D',
139 'ignored': 'I', 96 'ignored': 'I',
140 'missing': '!', 97 'missing': '!',
141 'modified': 'M', 98 'modified': 'M',
142 'normal': ' ', 99 'normal': ' ',
143 'replaced': 'R', 100 'replaced': 'R',
144 'unversioned': '?', 101 'unversioned': '?',
145 # TODO(maruel): Find the corresponding strings for X, ~ 102 # TODO(maruel): Find the corresponding strings for X, ~
146 } 103 }
147 output = RunShell(command) 104 output = RunShell(command)
148 dom = ParseXML(output) 105 dom = gclient.ParseXML(output)
149 results = [] 106 results = []
150 if dom: 107 if dom:
151 # /status/target/entry/(wc-status|commit|author|date) 108 # /status/target/entry/(wc-status|commit|author|date)
152 for target in dom.getElementsByTagName('target'): 109 for target in dom.getElementsByTagName('target'):
153 base_path = target.getAttribute('path') 110 base_path = target.getAttribute('path')
154 for entry in target.getElementsByTagName('entry'): 111 for entry in target.getElementsByTagName('entry'):
155 file = entry.getAttribute('path') 112 file = entry.getAttribute('path')
156 wc_status = entry.getElementsByTagName('wc-status') 113 wc_status = entry.getElementsByTagName('wc-status')
157 assert len(wc_status) == 1 114 assert len(wc_status) == 1
158 # Emulate svn 1.5 status ouput... 115 # Emulate svn 1.5 status ouput...
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 return [item[1] for item in GetSVNStatus(extra_args) if item[0][0] == '?'] 150 return [item[1] for item in GetSVNStatus(extra_args) if item[0][0] == '?']
194 151
195 152
196 def GetRepositoryRoot(): 153 def GetRepositoryRoot():
197 """Returns the top level directory of the current repository. 154 """Returns the top level directory of the current repository.
198 155
199 The directory is returned as an absolute path. 156 The directory is returned as an absolute path.
200 """ 157 """
201 global repository_root 158 global repository_root
202 if not repository_root: 159 if not repository_root:
203 cur_dir_repo_root = GetSVNFileInfo(os.getcwd()).get("Repository Root") 160 infos = gclient.CaptureSVNInfo(os.getcwd(), print_error=False)
161 cur_dir_repo_root = infos.get("Repository Root")
204 if not cur_dir_repo_root: 162 if not cur_dir_repo_root:
205 raise Exception("gcl run outside of repository") 163 raise Exception("gcl run outside of repository")
206 164
207 repository_root = os.getcwd() 165 repository_root = os.getcwd()
208 while True: 166 while True:
209 parent = os.path.dirname(repository_root) 167 parent = os.path.dirname(repository_root)
210 if GetSVNFileInfo(parent).get("Repository Root") != cur_dir_repo_root: 168 if (gclient.CaptureSVNInfo(parent).get("Repository Root") !=
169 cur_dir_repo_root):
211 break 170 break
212 repository_root = parent 171 repository_root = parent
213 return repository_root 172 return repository_root
214 173
215 174
216 def GetInfoDir(): 175 def GetInfoDir():
217 """Returns the directory where gcl info files are stored.""" 176 """Returns the directory where gcl info files are stored."""
218 global gcl_info_dir 177 global gcl_info_dir
219 if not gcl_info_dir: 178 if not gcl_info_dir:
220 gcl_info_dir = os.path.join(GetRepositoryRoot(), '.svn', 'gcl_info') 179 gcl_info_dir = os.path.join(GetRepositoryRoot(), '.svn', 'gcl_info')
221 return gcl_info_dir 180 return gcl_info_dir
222 181
223 182
224 def GetCodeReviewSetting(key): 183 def GetCodeReviewSetting(key):
225 """Returns a value for the given key for this repository.""" 184 """Returns a value for the given key for this repository."""
226 global read_gcl_info 185 global read_gcl_info
227 if not read_gcl_info: 186 if not read_gcl_info:
228 read_gcl_info = True 187 read_gcl_info = True
229 # First we check if we have a cached version. 188 # First we check if we have a cached version.
230 cached_settings_file = os.path.join(GetInfoDir(), CODEREVIEW_SETTINGS_FILE) 189 cached_settings_file = os.path.join(GetInfoDir(), CODEREVIEW_SETTINGS_FILE)
231 if (not os.path.exists(cached_settings_file) or 190 if (not os.path.exists(cached_settings_file) or
232 os.stat(cached_settings_file).st_mtime > 60*60*24*3): 191 os.stat(cached_settings_file).st_mtime > 60*60*24*3):
233 dir_info = GetSVNFileInfo(".") 192 dir_info = gclient.CaptureSVNInfo(".")
234 repo_root = dir_info["Repository Root"] 193 repo_root = dir_info["Repository Root"]
235 url_path = dir_info["URL"] 194 url_path = dir_info["URL"]
236 settings = "" 195 settings = ""
237 while True: 196 while True:
238 # Look for the codereview.settings file at the current level. 197 # Look for the codereview.settings file at the current level.
239 svn_path = url_path + "/" + CODEREVIEW_SETTINGS_FILE 198 svn_path = url_path + "/" + CODEREVIEW_SETTINGS_FILE
240 settings, rc = RunShellWithReturnCode(["svn", "cat", svn_path]) 199 settings, rc = RunShellWithReturnCode(["svn", "cat", svn_path])
241 if not rc: 200 if not rc:
242 # Exit the loop if the file was found. 201 # Exit the loop if the file was found.
243 break 202 break
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 previous_cwd = os.getcwd() 705 previous_cwd = os.getcwd()
747 if root is None: 706 if root is None:
748 os.chdir(GetRepositoryRoot()) 707 os.chdir(GetRepositoryRoot())
749 else: 708 else:
750 os.chdir(root) 709 os.chdir(root)
751 710
752 diff = [] 711 diff = []
753 for file in files: 712 for file in files:
754 # Use svn info output instead of os.path.isdir because the latter fails 713 # Use svn info output instead of os.path.isdir because the latter fails
755 # when the file is deleted. 714 # when the file is deleted.
756 if GetSVNFileInfo(file).get("Node Kind") in ("dir", "directory"): 715 if gclient.CaptureSVNInfo(file).get("Node Kind") in ("dir", "directory"):
757 continue 716 continue
758 # If the user specified a custom diff command in their svn config file, 717 # If the user specified a custom diff command in their svn config file,
759 # then it'll be used when we do svn diff, which we don't want to happen 718 # then it'll be used when we do svn diff, which we don't want to happen
760 # since we want the unified diff. Using --diff-cmd=diff doesn't always 719 # since we want the unified diff. Using --diff-cmd=diff doesn't always
761 # work, since they can have another diff executable in their path that 720 # work, since they can have another diff executable in their path that
762 # gives different line endings. So we use a bogus temp directory as the 721 # gives different line endings. So we use a bogus temp directory as the
763 # config directory, which gets around these problems. 722 # config directory, which gets around these problems.
764 if sys.platform.startswith("win"): 723 if sys.platform.startswith("win"):
765 parent_dir = tempfile.gettempdir() 724 parent_dir = tempfile.gettempdir()
766 else: 725 else:
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 # the files. This allows commands such as 'gcl diff xxx' to work. 1146 # the files. This allows commands such as 'gcl diff xxx' to work.
1188 args =["svn", command] 1147 args =["svn", command]
1189 root = GetRepositoryRoot() 1148 root = GetRepositoryRoot()
1190 args.extend([os.path.join(root, x) for x in change_info.FileList()]) 1149 args.extend([os.path.join(root, x) for x in change_info.FileList()])
1191 RunShell(args, True) 1150 RunShell(args, True)
1192 return 0 1151 return 0
1193 1152
1194 1153
1195 if __name__ == "__main__": 1154 if __name__ == "__main__":
1196 sys.exit(main()) 1155 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | presubmit.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698