| OLD | NEW |
| 1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2010 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 cStringIO | 7 import cStringIO |
| 8 import glob | 8 import glob |
| 9 import logging | 9 import logging |
| 10 import os | 10 import os |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 GIT.Capture(['config', '--get-regexp', r'^svn-remote\.'], cwd=cwd) | 137 GIT.Capture(['config', '--get-regexp', r'^svn-remote\.'], cwd=cwd) |
| 138 return True | 138 return True |
| 139 except gclient_utils.CheckCallError: | 139 except gclient_utils.CheckCallError: |
| 140 return False | 140 return False |
| 141 | 141 |
| 142 @staticmethod | 142 @staticmethod |
| 143 def GetSVNBranch(cwd): | 143 def GetSVNBranch(cwd): |
| 144 """Returns the svn branch name if found.""" | 144 """Returns the svn branch name if found.""" |
| 145 # Try to figure out which remote branch we're based on. | 145 # Try to figure out which remote branch we're based on. |
| 146 # Strategy: | 146 # Strategy: |
| 147 # 1) find all git-svn branches and note their svn URLs. | 147 # 1) iterate through our branch history and find the svn URL. |
| 148 # 2) iterate through our branch history and match up the URLs. | 148 # 2) find the svn-remote that fetches from the URL. |
| 149 | 149 |
| 150 # regexp matching the git-svn line that contains the URL. | 150 # regexp matching the git-svn line that contains the URL. |
| 151 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) | 151 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) |
| 152 | 152 |
| 153 # Get the refname and svn url for all refs/remotes/*. | 153 # We don't want to go through all of history, so read a line from the |
| 154 remotes = GIT.Capture( | 154 # pipe at a time. |
| 155 ['for-each-ref', '--format=%(refname)', 'refs/remotes'], | 155 # The -100 is an arbitrary limit so we don't search forever. |
| 156 cwd=cwd).splitlines() | 156 cmd = ['git', 'log', '-100', '--pretty=medium'] |
| 157 svn_refs = {} | 157 proc = gclient_utils.Popen(cmd, stdout=subprocess.PIPE) |
| 158 for ref in remotes: | 158 for line in proc.stdout: |
| 159 match = git_svn_re.search( | 159 match = git_svn_re.match(line) |
| 160 GIT.Capture(['cat-file', '-p', ref], cwd=cwd)) | 160 if match: |
| 161 # Prefer origin/HEAD over all others. | 161 url = match.group(1) |
| 162 if match and (match.group(1) not in svn_refs or | 162 proc.stdout.close() # Cut pipe. |
| 163 ref == "refs/remotes/origin/HEAD"): | 163 break |
| 164 svn_refs[match.group(1)] = ref | |
| 165 | 164 |
| 166 svn_branch = '' | 165 if url: |
| 167 if len(svn_refs) == 1: | 166 svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$') |
| 168 # Only one svn branch exists -- seems like a good candidate. | 167 remotes = GIT.Capture(['config', '--get-regexp', |
| 169 svn_branch = svn_refs.values()[0] | 168 r'^svn-remote\..*\.url'], cwd=cwd).splitlines() |
| 170 elif len(svn_refs) > 1: | 169 for remote in remotes: |
| 171 # We have more than one remote branch available. We don't | 170 match = svn_remote_re.match(remote) |
| 172 # want to go through all of history, so read a line from the | |
| 173 # pipe at a time. | |
| 174 # The -100 is an arbitrary limit so we don't search forever. | |
| 175 cmd = ['git', 'log', '-100', '--pretty=medium'] | |
| 176 proc = gclient_utils.Popen(cmd, stdout=subprocess.PIPE, cwd=cwd) | |
| 177 for line in proc.stdout: | |
| 178 match = git_svn_re.match(line) | |
| 179 if match: | 171 if match: |
| 180 url = match.group(1) | 172 remote = match.group(1) |
| 181 if url in svn_refs: | 173 base_url = match.group(2) |
| 182 svn_branch = svn_refs[url] | 174 fetch_spec = GIT.Capture( |
| 183 proc.stdout.close() # Cut pipe. | 175 ['config', 'svn-remote.%s.fetch' % remote], |
| 184 break | 176 cwd=cwd).strip().split(':') |
| 185 return svn_branch | 177 if fetch_spec[0]: |
| 178 full_url = base_url + '/' + fetch_spec[0] |
| 179 else: |
| 180 full_url = base_url |
| 181 if full_url == url: |
| 182 return fetch_spec[1] |
| 186 | 183 |
| 187 @staticmethod | 184 @staticmethod |
| 188 def FetchUpstreamTuple(cwd): | 185 def FetchUpstreamTuple(cwd): |
| 189 """Returns a tuple containg remote and remote ref, | 186 """Returns a tuple containg remote and remote ref, |
| 190 e.g. 'origin', 'refs/heads/master' | 187 e.g. 'origin', 'refs/heads/master' |
| 191 Tries to be intelligent and understand git-svn. | 188 Tries to be intelligent and understand git-svn. |
| 192 """ | 189 """ |
| 193 remote = '.' | 190 remote = '.' |
| 194 branch = GIT.GetBranch(cwd) | 191 branch = GIT.GetBranch(cwd) |
| 195 try: | 192 try: |
| 196 upstream_branch = GIT.Capture( | 193 upstream_branch = GIT.Capture( |
| 197 ['config', 'branch.%s.merge' % branch], cwd=cwd).strip() | 194 ['config', 'branch.%s.merge' % branch], cwd=cwd).strip() |
| 198 except gclient_utils.Error: | 195 except gclient_utils.Error: |
| 199 upstream_branch = None | 196 upstream_branch = None |
| 200 if upstream_branch: | 197 if upstream_branch: |
| 201 try: | 198 try: |
| 202 remote = GIT.Capture( | 199 remote = GIT.Capture( |
| 203 ['config', 'branch.%s.remote' % branch], cwd=cwd).strip() | 200 ['config', 'branch.%s.remote' % branch], cwd=cwd).strip() |
| 204 except gclient_utils.Error: | 201 except gclient_utils.Error: |
| 205 pass | 202 pass |
| 206 else: | 203 else: |
| 207 # Fall back on trying a git-svn upstream branch. | 204 try: |
| 208 if GIT.IsGitSvn(cwd): | 205 upstream_branch = GIT.Capture( |
| 209 upstream_branch = GIT.GetSVNBranch(cwd) | 206 ['config', 'rietveld.upstream-branch'], cwd=cwd).strip() |
| 207 except gclient_utils.Error: |
| 208 upstream_branch = None |
| 209 if upstream_branch: |
| 210 try: |
| 211 remote = GIT.Capture( |
| 212 ['config', 'rietveld.upstream-remote'], cwd=cwd).strip() |
| 213 except gclient_utils.Error: |
| 214 pass |
| 210 else: | 215 else: |
| 211 # Else, try to guess the origin remote. | 216 # Fall back on trying a git-svn upstream branch. |
| 212 remote_branches = GIT.Capture(['branch', '-r'], cwd=cwd).split() | 217 if GIT.IsGitSvn(cwd): |
| 213 if 'origin/master' in remote_branches: | 218 upstream_branch = GIT.GetSVNBranch(cwd) |
| 214 # Fall back on origin/master if it exits. | |
| 215 remote = 'origin' | |
| 216 upstream_branch = 'refs/heads/master' | |
| 217 elif 'origin/trunk' in remote_branches: | |
| 218 # Fall back on origin/trunk if it exists. Generally a shared | |
| 219 # git-svn clone | |
| 220 remote = 'origin' | |
| 221 upstream_branch = 'refs/heads/trunk' | |
| 222 else: | 219 else: |
| 223 # Give up. | 220 # Else, try to guess the origin remote. |
| 224 remote = None | 221 remote_branches = GIT.Capture(['branch', '-r'], cwd=cwd).split() |
| 225 upstream_branch = None | 222 if 'origin/master' in remote_branches: |
| 223 # Fall back on origin/master if it exits. |
| 224 remote = 'origin' |
| 225 upstream_branch = 'refs/heads/master' |
| 226 elif 'origin/trunk' in remote_branches: |
| 227 # Fall back on origin/trunk if it exists. Generally a shared |
| 228 # git-svn clone |
| 229 remote = 'origin' |
| 230 upstream_branch = 'refs/heads/trunk' |
| 231 else: |
| 232 # Give up. |
| 233 remote = None |
| 234 upstream_branch = None |
| 226 return remote, upstream_branch | 235 return remote, upstream_branch |
| 227 | 236 |
| 228 @staticmethod | 237 @staticmethod |
| 229 def GetUpstreamBranch(cwd): | 238 def GetUpstreamBranch(cwd): |
| 230 """Gets the current branch's upstream branch.""" | 239 """Gets the current branch's upstream branch.""" |
| 231 remote, upstream_branch = GIT.FetchUpstreamTuple(cwd) | 240 remote, upstream_branch = GIT.FetchUpstreamTuple(cwd) |
| 232 if remote != '.' and upstream_branch: | 241 if remote != '.' and upstream_branch: |
| 233 upstream_branch = upstream_branch.replace('heads', 'remotes/' + remote) | 242 upstream_branch = upstream_branch.replace('heads', 'remotes/' + remote) |
| 234 return upstream_branch | 243 return upstream_branch |
| 235 | 244 |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 elif os.path.isfile(file_path) or os.path.islink(file_path): | 889 elif os.path.isfile(file_path) or os.path.islink(file_path): |
| 881 logging.info('os.remove(%s)' % file_path) | 890 logging.info('os.remove(%s)' % file_path) |
| 882 os.remove(file_path) | 891 os.remove(file_path) |
| 883 elif os.path.isdir(file_path): | 892 elif os.path.isdir(file_path): |
| 884 logging.info('gclient_utils.RemoveDirectory(%s)' % file_path) | 893 logging.info('gclient_utils.RemoveDirectory(%s)' % file_path) |
| 885 gclient_utils.RemoveDirectory(file_path) | 894 gclient_utils.RemoveDirectory(file_path) |
| 886 else: | 895 else: |
| 887 logging.critical( | 896 logging.critical( |
| 888 ('No idea what is %s.\nYou just found a bug in gclient' | 897 ('No idea what is %s.\nYou just found a bug in gclient' |
| 889 ', please ping maruel@chromium.org ASAP!') % file_path) | 898 ', please ping maruel@chromium.org ASAP!') % file_path) |
| OLD | NEW |