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

Side by Side Diff: checkout.py

Issue 7085022: Add support for auto-props in the form: "*.sh = svn:eol-style=LF;svn:executable" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Update comment to be clearer Created 9 years, 6 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 | tests/checkout_test.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 # coding=utf8 1 # coding=utf8
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 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 """Manages a project checkout. 5 """Manages a project checkout.
6 6
7 Includes support for svn, git-svn and git. 7 Includes support for svn, git-svn and git.
8 """ 8 """
9 9
10 from __future__ import with_statement 10 from __future__ import with_statement
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 commit_pwd = None 170 commit_pwd = None
171 svn_url = None 171 svn_url = None
172 project_path = None 172 project_path = None
173 # Override at class level when necessary. If used, --non-interactive is 173 # Override at class level when necessary. If used, --non-interactive is
174 # implied. 174 # implied.
175 svn_config = SvnConfig() 175 svn_config = SvnConfig()
176 # Set to True when non-interactivity is necessary but a custom subversion 176 # Set to True when non-interactivity is necessary but a custom subversion
177 # configuration directory is not necessary. 177 # configuration directory is not necessary.
178 non_interactive = False 178 non_interactive = False
179 179
180 def _add_svn_flags(self, args, non_interactive): 180 def _add_svn_flags(self, args, non_interactive, credentials=True):
181 args = ['svn'] + args 181 args = ['svn'] + args
182 if not self.svn_config.default: 182 if not self.svn_config.default:
183 args.extend(['--config-dir', self.svn_config.svn_config_dir]) 183 args.extend(['--config-dir', self.svn_config.svn_config_dir])
184 if not self.svn_config.default or self.non_interactive or non_interactive: 184 if not self.svn_config.default or self.non_interactive or non_interactive:
185 args.append('--non-interactive') 185 args.append('--non-interactive')
186 if self.commit_user: 186 if credentials:
187 args.extend(['--username', self.commit_user]) 187 if self.commit_user:
188 if self.commit_pwd: 188 args.extend(['--username', self.commit_user])
189 args.extend(['--password', self.commit_pwd]) 189 if self.commit_pwd:
190 args.extend(['--password', self.commit_pwd])
190 return args 191 return args
191 192
192 def _check_call_svn(self, args, **kwargs): 193 def _check_call_svn(self, args, **kwargs):
193 """Runs svn and throws an exception if the command failed.""" 194 """Runs svn and throws an exception if the command failed."""
194 kwargs.setdefault('cwd', self.project_path) 195 kwargs.setdefault('cwd', self.project_path)
195 kwargs.setdefault('stdout', self.VOID) 196 kwargs.setdefault('stdout', self.VOID)
196 return subprocess2.check_call_out( 197 return subprocess2.check_call_out(
197 self._add_svn_flags(args, False), **kwargs) 198 self._add_svn_flags(args, False), **kwargs)
198 199
199 def _check_output_svn(self, args, **kwargs): 200 def _check_output_svn(self, args, credentials=True, **kwargs):
200 """Runs svn and throws an exception if the command failed. 201 """Runs svn and throws an exception if the command failed.
201 202
202 Returns the output. 203 Returns the output.
203 """ 204 """
204 kwargs.setdefault('cwd', self.project_path) 205 kwargs.setdefault('cwd', self.project_path)
205 return subprocess2.check_output(self._add_svn_flags(args, True), **kwargs) 206 return subprocess2.check_output(
207 self._add_svn_flags(args, True, credentials), **kwargs)
206 208
207 @staticmethod 209 @staticmethod
208 def _parse_svn_info(output, key): 210 def _parse_svn_info(output, key):
209 """Returns value for key from svn info output. 211 """Returns value for key from svn info output.
210 212
211 Case insensitive. 213 Case insensitive.
212 """ 214 """
213 values = {} 215 values = {}
214 key = key.lower() 216 key = key.lower()
215 for line in output.splitlines(False): 217 for line in output.splitlines(False):
(...skipping 25 matching lines...) Expand all
241 revision = self._revert() 243 revision = self._revert()
242 if revision != self._last_seen_revision: 244 if revision != self._last_seen_revision:
243 logging.info('Updated at revision %d' % revision) 245 logging.info('Updated at revision %d' % revision)
244 self._last_seen_revision = revision 246 self._last_seen_revision = revision
245 return revision 247 return revision
246 248
247 def apply_patch(self, patches, post_processor=None): 249 def apply_patch(self, patches, post_processor=None):
248 post_processor = post_processor or [] 250 post_processor = post_processor or []
249 for p in patches: 251 for p in patches:
250 try: 252 try:
253 # It is important to use credentials=False otherwise credentials could
254 # leak in the error message. Credentials are not necessary here for the
255 # following commands anyway.
251 stdout = '' 256 stdout = ''
252 if p.is_delete: 257 if p.is_delete:
253 stdout += self._check_output_svn(['delete', p.filename, '--force']) 258 stdout += self._check_output_svn(
259 ['delete', p.filename, '--force'], credentials=False)
254 else: 260 else:
255 new = not os.path.exists(p.filename) 261 new = not os.path.exists(p.filename)
256 262
257 # svn add while creating directories otherwise svn add on the 263 # svn add while creating directories otherwise svn add on the
258 # contained files will silently fail. 264 # contained files will silently fail.
259 # First, find the root directory that exists. 265 # First, find the root directory that exists.
260 dirname = os.path.dirname(p.filename) 266 dirname = os.path.dirname(p.filename)
261 dirs_to_create = [] 267 dirs_to_create = []
262 while (dirname and 268 while (dirname and
263 not os.path.isdir(os.path.join(self.project_path, dirname))): 269 not os.path.isdir(os.path.join(self.project_path, dirname))):
264 dirs_to_create.append(dirname) 270 dirs_to_create.append(dirname)
265 dirname = os.path.dirname(dirname) 271 dirname = os.path.dirname(dirname)
266 for dir_to_create in reversed(dirs_to_create): 272 for dir_to_create in reversed(dirs_to_create):
267 os.mkdir(os.path.join(self.project_path, dir_to_create)) 273 os.mkdir(os.path.join(self.project_path, dir_to_create))
268 stdout += self._check_output_svn( 274 stdout += self._check_output_svn(
269 ['add', dir_to_create, '--force']) 275 ['add', dir_to_create, '--force'], credentials=False)
270 276
271 if p.is_binary: 277 if p.is_binary:
272 with open(os.path.join(self.project_path, p.filename), 'wb') as f: 278 with open(os.path.join(self.project_path, p.filename), 'wb') as f:
273 f.write(p.get()) 279 f.write(p.get())
274 else: 280 else:
275 cmd = ['patch', '-p%s' % p.patchlevel, '--forward', '--force'] 281 cmd = ['patch', '-p%s' % p.patchlevel, '--forward', '--force']
276 stdout += subprocess2.check_output( 282 stdout += subprocess2.check_output(
277 cmd, stdin=p.get(), cwd=self.project_path) 283 cmd, stdin=p.get(), cwd=self.project_path)
278 if new: 284 if new:
279 stdout += self._check_output_svn(['add', p.filename, '--force']) 285 stdout += self._check_output_svn(
286 ['add', p.filename, '--force'], credentials=False)
280 for prop in p.svn_properties: 287 for prop in p.svn_properties:
281 stdout += self._check_output_svn( 288 stdout += self._check_output_svn(
282 ['propset', prop[0], prop[1], p.filename]) 289 ['propset', prop[0], prop[1], p.filename], credentials=False)
283 for prop, value in self.svn_config.auto_props.iteritems(): 290 for prop, values in self.svn_config.auto_props.iteritems():
284 if fnmatch.fnmatch(p.filename, prop): 291 if fnmatch.fnmatch(p.filename, prop):
285 stdout += self._check_output_svn( 292 for value in values.split(';'):
286 ['propset'] + value.split('=', 1) + [p.filename]) 293 if '=' not in value:
294 params = [value, '*']
295 else:
296 params = value.split('=', 1)
297 stdout += self._check_output_svn(
298 ['propset'] + params + [p.filename], credentials=False)
287 for post in post_processor: 299 for post in post_processor:
288 post(self, p) 300 post(self, p)
289 except OSError, e: 301 except OSError, e:
290 raise PatchApplicationFailed(p.filename, '%s%s' % (stdout, e)) 302 raise PatchApplicationFailed(p.filename, '%s%s' % (stdout, e))
291 except subprocess.CalledProcessError, e: 303 except subprocess.CalledProcessError, e:
292 raise PatchApplicationFailed( 304 raise PatchApplicationFailed(
293 p.filename, '%s%s' % (stdout, getattr(e, 'stdout', ''))) 305 p.filename,
306 'While running %s;\n%s%s' % (
307 ' '.join(e.cmd), stdout, getattr(e, 'stdout', '')))
294 308
295 def commit(self, commit_message, user): 309 def commit(self, commit_message, user):
296 logging.info('Committing patch for %s' % user) 310 logging.info('Committing patch for %s' % user)
297 assert self.commit_user 311 assert self.commit_user
298 assert isinstance(commit_message, unicode) 312 assert isinstance(commit_message, unicode)
299 handle, commit_filename = tempfile.mkstemp(text=True) 313 handle, commit_filename = tempfile.mkstemp(text=True)
300 try: 314 try:
301 # Shouldn't assume default encoding is UTF-8. But really, if you are using 315 # Shouldn't assume default encoding is UTF-8. But really, if you are using
302 # anything else, you are living in another world. 316 # anything else, you are living in another world.
303 os.write(handle, commit_message.encode('utf-8')) 317 os.write(handle, commit_message.encode('utf-8'))
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 user, message)) 659 user, message))
646 return 'FAKE' 660 return 'FAKE'
647 661
648 @property 662 @property
649 def project_name(self): 663 def project_name(self):
650 return self.checkout.project_name 664 return self.checkout.project_name
651 665
652 @property 666 @property
653 def project_path(self): 667 def project_path(self):
654 return self.checkout.project_path 668 return self.checkout.project_path
OLDNEW
« no previous file with comments | « no previous file | tests/checkout_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698