Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """SCM-specific utility classes.""" | 5 """SCM-specific utility classes.""" |
| 6 | 6 |
| 7 import glob | |
| 7 import os | 8 import os |
| 8 import re | 9 import re |
| 9 import shutil | 10 import shutil |
| 10 import subprocess | 11 import subprocess |
| 11 import sys | 12 import sys |
| 12 import tempfile | 13 import tempfile |
| 13 import xml.dom.minidom | 14 import xml.dom.minidom |
| 14 | 15 |
| 15 import gclient_utils | 16 import gclient_utils |
| 16 | 17 |
| 17 def ValidateEmail(email): | 18 def ValidateEmail(email): |
| 18 return (re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email) | 19 return (re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email) |
| 19 is not None) | 20 is not None) |
| 20 | 21 |
| 21 | 22 |
| 23 def GetCasedPath(path): | |
| 24 """Elcheapos way to get the real path case on Windows.""" | |
| 25 if sys.platform.startswith('win') and os.path.exists(path): | |
| 26 # Reconstruct the path. | |
| 27 path = os.path.abspath(path) | |
| 28 paths = path.split('\\') | |
|
bradn
2010/01/08 23:09:23
\\ -> os.pathsep
eh, whatever
| |
| 29 for i in range(len(paths)): | |
| 30 if i == 0: | |
| 31 # Skip drive letter. | |
| 32 continue | |
| 33 subpath = '\\'.join(paths[:i+1]) | |
| 34 prev = len('\\'.join(paths[:i])) | |
| 35 # glob.glob will return the cased path for the last item only. This is why | |
| 36 # we are calling it in a loop. Extract the data we want and put it back | |
| 37 # into the list. | |
| 38 paths[i] = glob.glob(subpath + '*')[0][prev+1:len(subpath)] | |
|
bradn
2010/01/08 23:09:23
Can you drop the '*' come to think of it, glob sho
bradn
2010/01/08 23:09:23
actually what happens if its the shortname? oh yuc
| |
| 39 path = '\\'.join(paths) | |
| 40 return path | |
| 41 | |
| 42 | |
| 22 class GIT(object): | 43 class GIT(object): |
| 23 COMMAND = "git" | 44 COMMAND = "git" |
| 24 | 45 |
| 25 @staticmethod | 46 @staticmethod |
| 26 def Capture(args, in_directory=None, print_error=True, error_ok=False): | 47 def Capture(args, in_directory=None, print_error=True, error_ok=False): |
| 27 """Runs git, capturing output sent to stdout as a string. | 48 """Runs git, capturing output sent to stdout as a string. |
| 28 | 49 |
| 29 Args: | 50 Args: |
| 30 args: A sequence of command line parameters to be passed to git. | 51 args: A sequence of command line parameters to be passed to git. |
| 31 in_directory: The directory where git is to be run. | 52 in_directory: The directory where git is to be run. |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 580 data = SVN.Capture(command, None) | 601 data = SVN.Capture(command, None) |
| 581 if data: | 602 if data: |
| 582 pass | 603 pass |
| 583 elif SVN.IsMoved(filename): | 604 elif SVN.IsMoved(filename): |
| 584 if full_move: | 605 if full_move: |
| 585 file_content = gclient_utils.FileRead(filename, 'rb') | 606 file_content = gclient_utils.FileRead(filename, 'rb') |
| 586 # Prepend '+' to every lines. | 607 # Prepend '+' to every lines. |
| 587 file_content = ['+' + i for i in file_content.splitlines(True)] | 608 file_content = ['+' + i for i in file_content.splitlines(True)] |
| 588 nb_lines = len(file_content) | 609 nb_lines = len(file_content) |
| 589 # We need to use / since patch on unix will fail otherwise. | 610 # We need to use / since patch on unix will fail otherwise. |
| 590 filename = filename.replace('\\', '/') | |
| 591 data = "Index: %s\n" % filename | 611 data = "Index: %s\n" % filename |
| 592 data += '=' * 67 + '\n' | 612 data += '=' * 67 + '\n' |
| 593 # Note: Should we use /dev/null instead? | 613 # Note: Should we use /dev/null instead? |
| 594 data += "--- %s\n" % filename | 614 data += "--- %s\n" % filename |
| 595 data += "+++ %s\n" % filename | 615 data += "+++ %s\n" % filename |
| 596 data += "@@ -0,0 +1,%d @@\n" % nb_lines | 616 data += "@@ -0,0 +1,%d @@\n" % nb_lines |
| 597 data += ''.join(file_content) | 617 data += ''.join(file_content) |
| 598 else: | 618 else: |
| 599 # svn diff on a mv/cp'd file outputs nothing. | 619 # svn diff on a mv/cp'd file outputs nothing. |
| 600 # We put in an empty Index entry so upload.py knows about them. | 620 # We put in an empty Index entry so upload.py knows about them. |
| 601 data = "Index: %s\n" % filename | 621 data = "Index: %s\n" % filename |
| 602 else: | 622 else: |
| 603 # The file is not modified anymore. It should be removed from the set. | 623 # The file is not modified anymore. It should be removed from the set. |
| 604 pass | 624 pass |
| 605 finally: | 625 finally: |
| 606 shutil.rmtree(bogus_dir) | 626 shutil.rmtree(bogus_dir) |
| 607 return data | 627 return data |
| 608 | 628 |
| 609 @staticmethod | 629 @staticmethod |
| 610 def GenerateDiff(filenames, root=None, full_move=False, revision=None): | 630 def GenerateDiff(filenames, root=None, full_move=False, revision=None): |
| 611 """Returns a string containing the diff for the given file list. | 631 """Returns a string containing the diff for the given file list. |
| 612 | 632 |
| 613 The files in the list should either be absolute paths or relative to the | 633 The files in the list should either be absolute paths or relative to the |
| 614 given root. If no root directory is provided, the repository root will be | 634 given root. If no root directory is provided, the repository root will be |
| 615 used. | 635 used. |
| 616 The diff will always use relative paths. | 636 The diff will always use relative paths. |
| 617 """ | 637 """ |
| 618 previous_cwd = os.getcwd() | 638 previous_cwd = os.getcwd() |
| 619 root = os.path.join(root or SVN.GetCheckoutRoot(previous_cwd), '') | 639 root = root or SVN.GetCheckoutRoot(previous_cwd) |
| 640 root = os.path.normcase(os.path.join(root, '')) | |
| 620 def RelativePath(path, root): | 641 def RelativePath(path, root): |
| 621 """We must use relative paths.""" | 642 """We must use relative paths.""" |
| 622 if path.startswith(root): | 643 if os.path.normcase(path).startswith(root): |
| 623 return path[len(root):] | 644 return path[len(root):] |
| 624 return path | 645 return path |
| 625 try: | 646 try: |
| 626 os.chdir(root) | 647 os.chdir(root) |
| 627 diff = "".join(filter(None, | 648 diff = "".join(filter(None, |
| 628 [SVN.DiffItem(RelativePath(f, root), | 649 [SVN.DiffItem(RelativePath(f, root), |
| 629 full_move=full_move, | 650 full_move=full_move, |
| 630 revision=revision) | 651 revision=revision) |
| 631 for f in filenames])) | 652 for f in filenames])) |
| 632 finally: | 653 finally: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 700 cur_dir_repo_root = infos.get("Repository Root") | 721 cur_dir_repo_root = infos.get("Repository Root") |
| 701 if not cur_dir_repo_root: | 722 if not cur_dir_repo_root: |
| 702 return None | 723 return None |
| 703 | 724 |
| 704 while True: | 725 while True: |
| 705 parent = os.path.dirname(directory) | 726 parent = os.path.dirname(directory) |
| 706 if (SVN.CaptureInfo(parent, print_error=False).get( | 727 if (SVN.CaptureInfo(parent, print_error=False).get( |
| 707 "Repository Root") != cur_dir_repo_root): | 728 "Repository Root") != cur_dir_repo_root): |
| 708 break | 729 break |
| 709 directory = parent | 730 directory = parent |
| 710 return directory | 731 return GetCasedPath(directory) |
| OLD | NEW |