| 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 os | 7 import os |
| 8 import re | 8 import re |
| 9 import shutil | 9 import shutil |
| 10 import subprocess | 10 import subprocess |
| 11 import sys | 11 import sys |
| 12 import tempfile | 12 import tempfile |
| 13 import xml.dom.minidom | 13 import xml.dom.minidom |
| 14 | 14 |
| 15 import gclient_utils | 15 import gclient_utils |
| 16 | 16 |
| 17 def ValidateEmail(email): |
| 18 return (re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email) |
| 19 is not None) |
| 20 |
| 17 | 21 |
| 18 class GIT(object): | 22 class GIT(object): |
| 19 COMMAND = "git" | 23 COMMAND = "git" |
| 20 | 24 |
| 21 @staticmethod | 25 @staticmethod |
| 22 def Capture(args, in_directory=None, print_error=True, error_ok=False): | 26 def Capture(args, in_directory=None, print_error=True, error_ok=False): |
| 23 """Runs git, capturing output sent to stdout as a string. | 27 """Runs git, capturing output sent to stdout as a string. |
| 24 | 28 |
| 25 Args: | 29 Args: |
| 26 args: A sequence of command line parameters to be passed to git. | 30 args: A sequence of command line parameters to be passed to git. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 return GIT.Capture(['config', 'user.email'], | 75 return GIT.Capture(['config', 'user.email'], |
| 72 repo_root, error_ok=True).strip() | 76 repo_root, error_ok=True).strip() |
| 73 | 77 |
| 74 @staticmethod | 78 @staticmethod |
| 75 def ShortBranchName(branch): | 79 def ShortBranchName(branch): |
| 76 """Converts a name like 'refs/heads/foo' to just 'foo'.""" | 80 """Converts a name like 'refs/heads/foo' to just 'foo'.""" |
| 77 return branch.replace('refs/heads/', '') | 81 return branch.replace('refs/heads/', '') |
| 78 | 82 |
| 79 @staticmethod | 83 @staticmethod |
| 80 def GetBranchRef(cwd): | 84 def GetBranchRef(cwd): |
| 85 """Returns the full branch reference, e.g. 'refs/heads/master'.""" |
| 86 return GIT.Capture(['symbolic-ref', 'HEAD'], cwd).strip() |
| 87 |
| 88 @staticmethod |
| 89 def GetBranch(cwd): |
| 81 """Returns the short branch name, e.g. 'master'.""" | 90 """Returns the short branch name, e.g. 'master'.""" |
| 82 return GIT.Capture(['symbolic-ref', 'HEAD'], cwd).strip() | 91 return GIT.ShortBranchName(GIT.BranchRef(cwd)) |
| 83 | 92 |
| 84 @staticmethod | 93 @staticmethod |
| 85 def IsGitSvn(cwd): | 94 def IsGitSvn(cwd): |
| 86 """Returns true if this repo looks like it's using git-svn.""" | 95 """Returns true if this repo looks like it's using git-svn.""" |
| 87 # If you have any "svn-remote.*" config keys, we think you're using svn. | 96 # If you have any "svn-remote.*" config keys, we think you're using svn. |
| 88 try: | 97 try: |
| 89 GIT.Capture(['config', '--get-regexp', r'^svn-remote\.'], cwd) | 98 GIT.Capture(['config', '--get-regexp', r'^svn-remote\.'], cwd) |
| 90 return True | 99 return True |
| 91 except gclient_utils.CheckCallError: | 100 except gclient_utils.CheckCallError: |
| 92 return False | 101 return False |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 proc.stdout.close() # Cut pipe. | 142 proc.stdout.close() # Cut pipe. |
| 134 break | 143 break |
| 135 return svn_branch | 144 return svn_branch |
| 136 | 145 |
| 137 @staticmethod | 146 @staticmethod |
| 138 def FetchUpstreamTuple(cwd): | 147 def FetchUpstreamTuple(cwd): |
| 139 """Returns a tuple containg remote and remote ref, | 148 """Returns a tuple containg remote and remote ref, |
| 140 e.g. 'origin', 'refs/heads/master' | 149 e.g. 'origin', 'refs/heads/master' |
| 141 """ | 150 """ |
| 142 remote = '.' | 151 remote = '.' |
| 143 branch = GIT.ShortBranchName(GIT.GetBranchRef(cwd)) | 152 branch = GIT.GetBranch(cwd) |
| 144 upstream_branch = None | 153 upstream_branch = None |
| 145 upstream_branch = GIT.Capture( | 154 upstream_branch = GIT.Capture( |
| 146 ['config', 'branch.%s.merge' % branch], error_ok=True).strip() | 155 ['config', 'branch.%s.merge' % branch], error_ok=True).strip() |
| 147 if upstream_branch: | 156 if upstream_branch: |
| 148 remote = GIT.Capture( | 157 remote = GIT.Capture( |
| 149 ['config', 'branch.%s.remote' % branch], | 158 ['config', 'branch.%s.remote' % branch], |
| 150 error_ok=True).strip() | 159 error_ok=True).strip() |
| 151 else: | 160 else: |
| 152 # Fall back on trying a git-svn upstream branch. | 161 # Fall back on trying a git-svn upstream branch. |
| 153 if GIT.IsGitSvn(cwd): | 162 if GIT.IsGitSvn(cwd): |
| (...skipping 20 matching lines...) Expand all Loading... |
| 174 branch = GIT.GetUpstream(cwd) | 183 branch = GIT.GetUpstream(cwd) |
| 175 diff = GIT.Capture(['diff-tree', '-p', '--no-prefix', branch, 'HEAD'], | 184 diff = GIT.Capture(['diff-tree', '-p', '--no-prefix', branch, 'HEAD'], |
| 176 cwd).splitlines(True) | 185 cwd).splitlines(True) |
| 177 for i in range(len(diff)): | 186 for i in range(len(diff)): |
| 178 # In the case of added files, replace /dev/null with the path to the | 187 # In the case of added files, replace /dev/null with the path to the |
| 179 # file being added. | 188 # file being added. |
| 180 if diff[i].startswith('--- /dev/null'): | 189 if diff[i].startswith('--- /dev/null'): |
| 181 diff[i] = '--- %s' % diff[i+1][4:] | 190 diff[i] = '--- %s' % diff[i+1][4:] |
| 182 return ''.join(diff) | 191 return ''.join(diff) |
| 183 | 192 |
| 193 @staticmethod |
| 194 def GetPatchName(cwd): |
| 195 """Constructs a name for this patch.""" |
| 196 short_sha = GIT.Capture(['rev-parse', '--short=4', 'HEAD'], cwd).strip() |
| 197 return "%s-%s" % (GIT.GetBranch(cwd), short_sha) |
| 198 |
| 199 @staticmethod |
| 200 def GetCheckoutRoot(cwd): |
| 201 """Returns the top level directory of the current repository. |
| 202 |
| 203 The directory is returned as an absolute path. |
| 204 """ |
| 205 return os.path.abspath(GIT.Capture(['rev-parse', '--show-cdup'], |
| 206 cwd).strip()) |
| 207 |
| 184 | 208 |
| 185 class SVN(object): | 209 class SVN(object): |
| 186 COMMAND = "svn" | 210 COMMAND = "svn" |
| 187 | 211 |
| 188 @staticmethod | 212 @staticmethod |
| 189 def Run(args, in_directory): | 213 def Run(args, in_directory): |
| 190 """Runs svn, sending output to stdout. | 214 """Runs svn, sending output to stdout. |
| 191 | 215 |
| 192 Args: | 216 Args: |
| 193 args: A sequence of command line parameters to be passed to svn. | 217 args: A sequence of command line parameters to be passed to svn. |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 if not cur_dir_repo_root: | 660 if not cur_dir_repo_root: |
| 637 return None | 661 return None |
| 638 | 662 |
| 639 while True: | 663 while True: |
| 640 parent = os.path.dirname(directory) | 664 parent = os.path.dirname(directory) |
| 641 if (SVN.CaptureInfo(parent, print_error=False).get( | 665 if (SVN.CaptureInfo(parent, print_error=False).get( |
| 642 "Repository Root") != cur_dir_repo_root): | 666 "Repository Root") != cur_dir_repo_root): |
| 643 break | 667 break |
| 644 directory = parent | 668 directory = parent |
| 645 return directory | 669 return directory |
| OLD | NEW |