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

Side by Side Diff: presubmit_support.py

Issue 113783: Factor out SVN-specific methods out of AffectedFile. (Closed)
Patch Set: 80 cols 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
« no previous file with comments | « no previous file | tests/presubmit_unittest.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 """Enables directory-specific presubmit checks to run at upload and/or commit. 6 """Enables directory-specific presubmit checks to run at upload and/or commit.
7 """ 7 """
8 8
9 __version__ = '1.0.1' 9 __version__ = '1.0.1'
10 10
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 for line in lines: 317 for line in lines:
318 line_number += 1 318 line_number += 1
319 yield (af, line_number, line) 319 yield (af, line_number, line)
320 320
321 321
322 class AffectedFile(object): 322 class AffectedFile(object):
323 """Representation of a file in a change.""" 323 """Representation of a file in a change."""
324 324
325 def __init__(self, path, action, repository_root=''): 325 def __init__(self, path, action, repository_root=''):
326 self.path = path 326 self.path = path
327 self.action = action.strip() 327 self.action = action
328 self.repository_root = repository_root 328 self.repository_root = repository_root
329 self.server_path = None
330 self.is_directory = None
331 self.properties = {}
329 332
330 def ServerPath(self): 333 def ServerPath(self):
331 """Returns a path string that identifies the file in the SCM system. 334 """Returns a path string that identifies the file in the SCM system.
332 335
333 Returns the empty string if the file does not exist in SCM. 336 Returns the empty string if the file does not exist in SCM.
334 """ 337 """
335 return gclient.CaptureSVNInfo(self.AbsoluteLocalPath()).get('URL', '') 338 return ""
336 339
337 def LocalPath(self): 340 def LocalPath(self):
338 """Returns the path of this file on the local disk relative to client root. 341 """Returns the path of this file on the local disk relative to client root.
339 """ 342 """
340 return normpath(self.path) 343 return normpath(self.path)
341 344
342 def AbsoluteLocalPath(self): 345 def AbsoluteLocalPath(self):
343 """Returns the absolute path of this file on the local disk. 346 """Returns the absolute path of this file on the local disk.
344 """ 347 """
345 return normpath(os.path.join(self.repository_root, self.LocalPath())) 348 return normpath(os.path.join(self.repository_root, self.LocalPath()))
346 349
347 def IsDirectory(self): 350 def IsDirectory(self):
348 """Returns true if this object is a directory.""" 351 """Returns true if this object is a directory."""
349 path = self.AbsoluteLocalPath() 352 path = self.AbsoluteLocalPath()
350 if os.path.exists(path): 353 if self.is_directory is None:
351 # Retrieve directly from the file system; it is much faster than querying 354 self.is_directory = (os.path.exists(path) and
352 # subversion, especially on Windows. 355 os.path.isdir(path))
353 return os.path.isdir(path) 356 return self.is_directory
354 else:
355 return gclient.CaptureSVNInfo(path).get('Node Kind') in ('dir',
356 'directory')
357
358 def SvnProperty(self, property_name):
359 """Returns the specified SVN property of this file, or the empty string
360 if no such property.
361 """
362 return gcl.GetSVNFileProperty(self.AbsoluteLocalPath(), property_name)
363 357
364 def Action(self): 358 def Action(self):
365 """Returns the action on this opened file, e.g. A, M, D, etc.""" 359 """Returns the action on this opened file, e.g. A, M, D, etc."""
360 # TODO(maruel): Somewhat crappy, Could be "A" or "A +" for svn but
361 # different for other SCM.
366 return self.action 362 return self.action
367 363
364 def Property(self, property_name):
365 """Returns the specified SCM property of this file, or None if no such
366 property.
367 """
368 return self.properties.get(property_name, None)
369
368 def NewContents(self): 370 def NewContents(self):
369 """Returns an iterator over the lines in the new version of file. 371 """Returns an iterator over the lines in the new version of file.
370 372
371 The new version is the file in the user's workspace, i.e. the "right hand 373 The new version is the file in the user's workspace, i.e. the "right hand
372 side". 374 side".
373 375
374 Contents will be empty if the file is a directory or does not exist. 376 Contents will be empty if the file is a directory or does not exist.
375 """ 377 """
376 if self.IsDirectory(): 378 if self.IsDirectory():
377 return [] 379 return []
(...skipping 10 matching lines...) Expand all
388 def OldFileTempPath(self): 390 def OldFileTempPath(self):
389 """Returns the path on local disk where the old contents resides. 391 """Returns the path on local disk where the old contents resides.
390 392
391 The old version is the file in depot, i.e. the "left hand side". 393 The old version is the file in depot, i.e. the "left hand side".
392 This is a read-only cached copy of the old contents. *DO NOT* try to 394 This is a read-only cached copy of the old contents. *DO NOT* try to
393 modify this file. 395 modify this file.
394 """ 396 """
395 raise NotImplementedError() # Implement if/when needed. 397 raise NotImplementedError() # Implement if/when needed.
396 398
397 399
400 class SvnAffectedFile(AffectedFile):
401 def ServerPath(self):
402 if self.server_path is None:
403 self.server_path = gclient.CaptureSVNInfo(
404 self.AbsoluteLocalPath()).get('URL', '')
405 return self.server_path
406
407 def IsDirectory(self):
408 path = self.AbsoluteLocalPath()
409 if self.is_directory is None:
410 if os.path.exists(path):
411 # Retrieve directly from the file system; it is much faster than
412 # querying subversion, especially on Windows.
413 self.is_directory = os.path.isdir(path)
414 else:
415 self.is_directory = gclient.CaptureSVNInfo(
416 path).get('Node Kind') in ('dir', 'directory')
417 return self.is_directory
418
419 def Property(self, property_name):
420 if not property_name in self.properties:
421 self.properties[property_name] = gcl.GetSVNFileProperty(
422 self.AbsoluteLocalPath(), property_name)
423 return self.properties[property_name]
424
425
398 class GclChange(object): 426 class GclChange(object):
399 """A gcl change. See gcl.ChangeInfo for more info.""" 427 """A gcl change. See gcl.ChangeInfo for more info."""
400 428
401 def __init__(self, change_info, repository_root=''): 429 def __init__(self, change_info, repository_root=''):
402 self.name = change_info.name 430 self.name = change_info.name
403 self.full_description = change_info.description 431 self.full_description = change_info.description
404 self.repository_root = repository_root 432 self.repository_root = repository_root
405 433
406 # From the description text, build up a dictionary of key/value pairs 434 # From the description text, build up a dictionary of key/value pairs
407 # plus the description minus all key/value or "tag" lines. 435 # plus the description minus all key/value or "tag" lines.
408 self.description_without_tags = [] 436 self.description_without_tags = []
409 self.tags = {} 437 self.tags = {}
410 for line in change_info.description.splitlines(): 438 for line in change_info.description.splitlines():
411 m = _tag_line_re.match(line) 439 m = _tag_line_re.match(line)
412 if m: 440 if m:
413 self.tags[m.group('key')] = m.group('value') 441 self.tags[m.group('key')] = m.group('value')
414 else: 442 else:
415 self.description_without_tags.append(line) 443 self.description_without_tags.append(line)
416 444
417 # Change back to text and remove whitespace at end. 445 # Change back to text and remove whitespace at end.
418 self.description_without_tags = '\n'.join(self.description_without_tags) 446 self.description_without_tags = '\n'.join(self.description_without_tags)
419 self.description_without_tags = self.description_without_tags.rstrip() 447 self.description_without_tags = self.description_without_tags.rstrip()
420 448
421 self.affected_files = [AffectedFile(info[1], info[0], repository_root) for 449 self.affected_files = [
422 info in change_info.files] 450 SvnAffectedFile(info[1], info[0].strip(), repository_root)
451 for info in change_info.files
452 ]
423 453
424 def Change(self): 454 def Change(self):
425 """Returns the change name.""" 455 """Returns the change name."""
426 return self.name 456 return self.name
427 457
428 def Changelist(self): 458 def Changelist(self):
429 """Synonym for Change().""" 459 """Synonym for Change()."""
430 return self.Change() 460 return self.Change()
431 461
432 def DescriptionText(self): 462 def DescriptionText(self):
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 574
545 checked_dirs[dir] = '' 575 checked_dirs[dir] = ''
546 if dir in ['', '.']: 576 if dir in ['', '.']:
547 break 577 break
548 else: 578 else:
549 dir = os.path.dirname(dir) 579 dir = os.path.dirname(dir)
550 return presubmit_files 580 return presubmit_files
551 581
552 582
553 class PresubmitExecuter(object): 583 class PresubmitExecuter(object):
554
555 def __init__(self, change_info, committing): 584 def __init__(self, change_info, committing):
556 """ 585 """
557 Args: 586 Args:
558 change_info: The ChangeInfo object for the change. 587 change_info: The ChangeInfo object for the change.
559 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 588 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
560 """ 589 """
561 self.change = GclChange(change_info, gcl.GetRepositoryRoot()) 590 self.change = GclChange(change_info, gcl.GetRepositoryRoot())
562 self.committing = committing 591 self.committing = committing
563 592
564 def ExecPresubmitScript(self, script_text, presubmit_path): 593 def ExecPresubmitScript(self, script_text, presubmit_path):
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), 740 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files),
712 options.commit, 741 options.commit,
713 options.verbose, 742 options.verbose,
714 sys.stdout, 743 sys.stdout,
715 sys.stdin, 744 sys.stdin,
716 default_presubmit=None) 745 default_presubmit=None)
717 746
718 747
719 if __name__ == '__main__': 748 if __name__ == '__main__':
720 sys.exit(Main(sys.argv)) 749 sys.exit(Main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | tests/presubmit_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698