| OLD | NEW |
| 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.1' | 9 __version__ = '1.1' |
| 10 | 10 |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 line_number = 0 | 309 line_number = 0 |
| 310 for line in lines: | 310 for line in lines: |
| 311 line_number += 1 | 311 line_number += 1 |
| 312 yield (af, line_number, line) | 312 yield (af, line_number, line) |
| 313 | 313 |
| 314 | 314 |
| 315 class AffectedFile(object): | 315 class AffectedFile(object): |
| 316 """Representation of a file in a change.""" | 316 """Representation of a file in a change.""" |
| 317 | 317 |
| 318 def __init__(self, path, action, repository_root=''): | 318 def __init__(self, path, action, repository_root=''): |
| 319 self.path = path | 319 self._path = path |
| 320 self.action = action | 320 self._action = action |
| 321 self.repository_root = repository_root | 321 self._repository_root = repository_root |
| 322 self.server_path = None | 322 self._is_directory = None |
| 323 self.is_directory = None | 323 self._properties = {} |
| 324 self.properties = {} | |
| 325 | 324 |
| 326 def ServerPath(self): | 325 def ServerPath(self): |
| 327 """Returns a path string that identifies the file in the SCM system. | 326 """Returns a path string that identifies the file in the SCM system. |
| 328 | 327 |
| 329 Returns the empty string if the file does not exist in SCM. | 328 Returns the empty string if the file does not exist in SCM. |
| 330 """ | 329 """ |
| 331 return "" | 330 return "" |
| 332 | 331 |
| 333 def LocalPath(self): | 332 def LocalPath(self): |
| 334 """Returns the path of this file on the local disk relative to client root. | 333 """Returns the path of this file on the local disk relative to client root. |
| 335 """ | 334 """ |
| 336 return normpath(self.path) | 335 return normpath(self._path) |
| 337 | 336 |
| 338 def AbsoluteLocalPath(self): | 337 def AbsoluteLocalPath(self): |
| 339 """Returns the absolute path of this file on the local disk. | 338 """Returns the absolute path of this file on the local disk. |
| 340 """ | 339 """ |
| 341 return normpath(os.path.join(self.repository_root, self.LocalPath())) | 340 return normpath(os.path.join(self._repository_root, self.LocalPath())) |
| 342 | 341 |
| 343 def IsDirectory(self): | 342 def IsDirectory(self): |
| 344 """Returns true if this object is a directory.""" | 343 """Returns true if this object is a directory.""" |
| 345 path = self.AbsoluteLocalPath() | 344 if self._is_directory is None: |
| 346 if self.is_directory is None: | 345 path = self.AbsoluteLocalPath() |
| 347 self.is_directory = (os.path.exists(path) and | 346 self._is_directory = (os.path.exists(path) and |
| 348 os.path.isdir(path)) | 347 os.path.isdir(path)) |
| 349 return self.is_directory | 348 return self._is_directory |
| 350 | 349 |
| 351 def Action(self): | 350 def Action(self): |
| 352 """Returns the action on this opened file, e.g. A, M, D, etc.""" | 351 """Returns the action on this opened file, e.g. A, M, D, etc.""" |
| 353 # TODO(maruel): Somewhat crappy, Could be "A" or "A +" for svn but | 352 # TODO(maruel): Somewhat crappy, Could be "A" or "A +" for svn but |
| 354 # different for other SCM. | 353 # different for other SCM. |
| 355 return self.action | 354 return self._action |
| 356 | 355 |
| 357 def Property(self, property_name): | 356 def Property(self, property_name): |
| 358 """Returns the specified SCM property of this file, or None if no such | 357 """Returns the specified SCM property of this file, or None if no such |
| 359 property. | 358 property. |
| 360 """ | 359 """ |
| 361 return self.properties.get(property_name, None) | 360 return self._properties.get(property_name, None) |
| 362 | 361 |
| 363 def IsTextFile(self): | 362 def IsTextFile(self): |
| 364 """Returns True if the file is a text file and not a binary file.""" | 363 """Returns True if the file is a text file and not a binary file.""" |
| 365 raise NotImplementedError() # Implement when needed | 364 raise NotImplementedError() # Implement when needed |
| 366 | 365 |
| 367 def NewContents(self): | 366 def NewContents(self): |
| 368 """Returns an iterator over the lines in the new version of file. | 367 """Returns an iterator over the lines in the new version of file. |
| 369 | 368 |
| 370 The new version is the file in the user's workspace, i.e. the "right hand | 369 The new version is the file in the user's workspace, i.e. the "right hand |
| 371 side". | 370 side". |
| (...skipping 18 matching lines...) Expand all Loading... |
| 390 The old version is the file in depot, i.e. the "left hand side". | 389 The old version is the file in depot, i.e. the "left hand side". |
| 391 This is a read-only cached copy of the old contents. *DO NOT* try to | 390 This is a read-only cached copy of the old contents. *DO NOT* try to |
| 392 modify this file. | 391 modify this file. |
| 393 """ | 392 """ |
| 394 raise NotImplementedError() # Implement if/when needed. | 393 raise NotImplementedError() # Implement if/when needed. |
| 395 | 394 |
| 396 | 395 |
| 397 class SvnAffectedFile(AffectedFile): | 396 class SvnAffectedFile(AffectedFile): |
| 398 """Representation of a file in a change out of a Subversion checkout.""" | 397 """Representation of a file in a change out of a Subversion checkout.""" |
| 399 | 398 |
| 399 def __init__(self, *args, **kwargs): |
| 400 AffectedFile.__init__(self, *args, **kwargs) |
| 401 self._server_path = None |
| 402 self._is_text_file = None |
| 403 |
| 400 def ServerPath(self): | 404 def ServerPath(self): |
| 401 if self.server_path is None: | 405 if self._server_path is None: |
| 402 self.server_path = gclient.CaptureSVNInfo( | 406 self._server_path = gclient.CaptureSVNInfo( |
| 403 self.AbsoluteLocalPath()).get('URL', '') | 407 self.AbsoluteLocalPath()).get('URL', '') |
| 404 return self.server_path | 408 return self._server_path |
| 405 | 409 |
| 406 def IsDirectory(self): | 410 def IsDirectory(self): |
| 407 path = self.AbsoluteLocalPath() | 411 if self._is_directory is None: |
| 408 if self.is_directory is None: | 412 path = self.AbsoluteLocalPath() |
| 409 if os.path.exists(path): | 413 if os.path.exists(path): |
| 410 # Retrieve directly from the file system; it is much faster than | 414 # Retrieve directly from the file system; it is much faster than |
| 411 # querying subversion, especially on Windows. | 415 # querying subversion, especially on Windows. |
| 412 self.is_directory = os.path.isdir(path) | 416 self._is_directory = os.path.isdir(path) |
| 413 else: | 417 else: |
| 414 self.is_directory = gclient.CaptureSVNInfo( | 418 self._is_directory = gclient.CaptureSVNInfo( |
| 415 path).get('Node Kind') in ('dir', 'directory') | 419 path).get('Node Kind') in ('dir', 'directory') |
| 416 return self.is_directory | 420 return self._is_directory |
| 417 | 421 |
| 418 def Property(self, property_name): | 422 def Property(self, property_name): |
| 419 if not property_name in self.properties: | 423 if not property_name in self._properties: |
| 420 self.properties[property_name] = gcl.GetSVNFileProperty( | 424 self._properties[property_name] = gcl.GetSVNFileProperty( |
| 421 self.AbsoluteLocalPath(), property_name) | 425 self.AbsoluteLocalPath(), property_name) |
| 422 return self.properties[property_name] | 426 return self._properties[property_name] |
| 423 | 427 |
| 424 def IsTextFile(self): | 428 def IsTextFile(self): |
| 425 if self.Action() == 'D': | 429 if self._is_text_file is None: |
| 426 return False | 430 if self.Action() == 'D': |
| 427 mime_type = gcl.GetSVNFileProperty(self.AbsoluteLocalPath(), | 431 # A deleted file is not a text file. |
| 428 'svn:mime-type') | 432 self._is_text_file = False |
| 429 if not mime_type or mime_type.startswith('text/'): | 433 elif self.IsDirectory(): |
| 430 return True | 434 self._is_text_file = False |
| 431 return False | 435 else: |
| 436 mime_type = gcl.GetSVNFileProperty(self.AbsoluteLocalPath(), |
| 437 'svn:mime-type') |
| 438 self._is_text_file = (not mime_type or mime_type.startswith('text/')) |
| 439 return self._is_text_file |
| 432 | 440 |
| 433 | 441 |
| 434 class GclChange(object): | 442 class GclChange(object): |
| 435 """Describe a change. | 443 """Describe a change. |
| 436 | 444 |
| 437 Used directly by the presubmit scripts to query the current change being | 445 Used directly by the presubmit scripts to query the current change being |
| 438 tested. | 446 tested. |
| 439 | 447 |
| 440 Instance members: | 448 Instance members: |
| 441 tags: Dictionnary of KEY=VALUE pairs found in the change description. | 449 tags: Dictionnary of KEY=VALUE pairs found in the change description. |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), | 763 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), |
| 756 options.commit, | 764 options.commit, |
| 757 options.verbose, | 765 options.verbose, |
| 758 sys.stdout, | 766 sys.stdout, |
| 759 sys.stdin, | 767 sys.stdin, |
| 760 default_presubmit=None) | 768 default_presubmit=None) |
| 761 | 769 |
| 762 | 770 |
| 763 if __name__ == '__main__': | 771 if __name__ == '__main__': |
| 764 sys.exit(Main(sys.argv)) | 772 sys.exit(Main(sys.argv)) |
| OLD | NEW |