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 |