OLD | NEW |
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 if val.isdigit(): | 90 if val.isdigit(): |
91 return int(val) | 91 return int(val) |
92 else: | 92 else: |
93 return 0 | 93 return 0 |
94 | 94 |
95 | 95 |
96 class GIT(object): | 96 class GIT(object): |
97 current_version = None | 97 current_version = None |
98 | 98 |
99 @staticmethod | 99 @staticmethod |
100 def Capture(args, **kwargs): | 100 def Capture(args, cwd, **kwargs): |
101 return subprocess2.check_output( | 101 return subprocess2.check_output( |
102 ['git'] + args, stderr=subprocess2.PIPE, **kwargs) | 102 ['git'] + args, cwd=cwd, stderr=subprocess2.PIPE, **kwargs) |
103 | 103 |
104 @staticmethod | 104 @staticmethod |
105 def CaptureStatus(files, upstream_branch=None): | 105 def CaptureStatus(files, cwd, upstream_branch): |
106 """Returns git status. | 106 """Returns git status. |
107 | 107 |
108 @files can be a string (one file) or a list of files. | 108 @files can be a string (one file) or a list of files. |
109 | 109 |
110 Returns an array of (status, file) tuples.""" | 110 Returns an array of (status, file) tuples.""" |
111 if upstream_branch is None: | 111 if upstream_branch is None: |
112 upstream_branch = GIT.GetUpstreamBranch(os.getcwd()) | 112 upstream_branch = GIT.GetUpstreamBranch(cwd) |
113 if upstream_branch is None: | 113 if upstream_branch is None: |
114 raise gclient_utils.Error('Cannot determine upstream branch') | 114 raise gclient_utils.Error('Cannot determine upstream branch') |
115 command = ['diff', '--name-status', '-r', '%s...' % upstream_branch] | 115 command = ['diff', '--name-status', '-r', '%s...' % upstream_branch] |
116 if not files: | 116 if not files: |
117 pass | 117 pass |
118 elif isinstance(files, basestring): | 118 elif isinstance(files, basestring): |
119 command.append(files) | 119 command.append(files) |
120 else: | 120 else: |
121 command.extend(files) | 121 command.extend(files) |
122 status = GIT.Capture(command).rstrip() | 122 status = GIT.Capture(command, cwd).rstrip() |
123 results = [] | 123 results = [] |
124 if status: | 124 if status: |
125 for statusline in status.splitlines(): | 125 for statusline in status.splitlines(): |
126 # 3-way merges can cause the status can be 'MMM' instead of 'M'. This | 126 # 3-way merges can cause the status can be 'MMM' instead of 'M'. This |
127 # can happen when the user has 2 local branches and he diffs between | 127 # can happen when the user has 2 local branches and he diffs between |
128 # these 2 branches instead diffing to upstream. | 128 # these 2 branches instead diffing to upstream. |
129 m = re.match('^(\w)+\t(.+)$', statusline) | 129 m = re.match('^(\w)+\t(.+)$', statusline) |
130 if not m: | 130 if not m: |
131 raise gclient_utils.Error( | 131 raise gclient_utils.Error( |
132 'status currently unsupported: %s' % statusline) | 132 'status currently unsupported: %s' % statusline) |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 # 1) iterate through our branch history and find the svn URL. | 219 # 1) iterate through our branch history and find the svn URL. |
220 # 2) find the svn-remote that fetches from the URL. | 220 # 2) find the svn-remote that fetches from the URL. |
221 | 221 |
222 # regexp matching the git-svn line that contains the URL. | 222 # regexp matching the git-svn line that contains the URL. |
223 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) | 223 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) |
224 | 224 |
225 # We don't want to go through all of history, so read a line from the | 225 # We don't want to go through all of history, so read a line from the |
226 # pipe at a time. | 226 # pipe at a time. |
227 # The -100 is an arbitrary limit so we don't search forever. | 227 # The -100 is an arbitrary limit so we don't search forever. |
228 cmd = ['git', 'log', '-100', '--pretty=medium'] | 228 cmd = ['git', 'log', '-100', '--pretty=medium'] |
229 proc = subprocess2.Popen(cmd, stdout=subprocess2.PIPE) | 229 proc = subprocess2.Popen(cmd, cwd, stdout=subprocess2.PIPE) |
230 url = None | 230 url = None |
231 for line in proc.stdout: | 231 for line in proc.stdout: |
232 match = git_svn_re.match(line) | 232 match = git_svn_re.match(line) |
233 if match: | 233 if match: |
234 url = match.group(1) | 234 url = match.group(1) |
235 proc.stdout.close() # Cut pipe. | 235 proc.stdout.close() # Cut pipe. |
236 break | 236 break |
237 | 237 |
238 if url: | 238 if url: |
239 svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$') | 239 svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$') |
240 remotes = GIT.Capture(['config', '--get-regexp', | 240 remotes = GIT.Capture( |
241 r'^svn-remote\..*\.url'], cwd=cwd).splitlines() | 241 ['config', '--get-regexp', r'^svn-remote\..*\.url'], |
| 242 cwd=cwd).splitlines() |
242 for remote in remotes: | 243 for remote in remotes: |
243 match = svn_remote_re.match(remote) | 244 match = svn_remote_re.match(remote) |
244 if match: | 245 if match: |
245 remote = match.group(1) | 246 remote = match.group(1) |
246 base_url = match.group(2) | 247 base_url = match.group(2) |
247 try: | 248 try: |
248 fetch_spec = GIT.Capture( | 249 fetch_spec = GIT.Capture( |
249 ['config', 'svn-remote.%s.fetch' % remote], | 250 ['config', 'svn-remote.%s.fetch' % remote], |
250 cwd=cwd).strip() | 251 cwd=cwd).strip() |
251 branch = GIT.MatchSvnGlob(url, base_url, fetch_spec, False) | 252 branch = GIT.MatchSvnGlob(url, base_url, fetch_spec, False) |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 def GetCheckoutRoot(cwd): | 377 def GetCheckoutRoot(cwd): |
377 """Returns the top level directory of a git checkout as an absolute path. | 378 """Returns the top level directory of a git checkout as an absolute path. |
378 """ | 379 """ |
379 root = GIT.Capture(['rev-parse', '--show-cdup'], cwd=cwd).strip() | 380 root = GIT.Capture(['rev-parse', '--show-cdup'], cwd=cwd).strip() |
380 return os.path.abspath(os.path.join(cwd, root)) | 381 return os.path.abspath(os.path.join(cwd, root)) |
381 | 382 |
382 @classmethod | 383 @classmethod |
383 def AssertVersion(cls, min_version): | 384 def AssertVersion(cls, min_version): |
384 """Asserts git's version is at least min_version.""" | 385 """Asserts git's version is at least min_version.""" |
385 if cls.current_version is None: | 386 if cls.current_version is None: |
386 cls.current_version = cls.Capture(['--version']).split()[-1] | 387 cls.current_version = cls.Capture(['--version'], '.').split()[-1] |
387 current_version_list = map(only_int, cls.current_version.split('.')) | 388 current_version_list = map(only_int, cls.current_version.split('.')) |
388 for min_ver in map(int, min_version.split('.')): | 389 for min_ver in map(int, min_version.split('.')): |
389 ver = current_version_list.pop(0) | 390 ver = current_version_list.pop(0) |
390 if ver < min_ver: | 391 if ver < min_ver: |
391 return (False, cls.current_version) | 392 return (False, cls.current_version) |
392 elif ver > min_ver: | 393 elif ver > min_ver: |
393 return (True, cls.current_version) | 394 return (True, cls.current_version) |
394 return (True, cls.current_version) | 395 return (True, cls.current_version) |
395 | 396 |
396 | 397 |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 # revert, like for properties. | 1004 # revert, like for properties. |
1004 if not os.path.isdir(cwd): | 1005 if not os.path.isdir(cwd): |
1005 # '.' was deleted. It's not worth continuing. | 1006 # '.' was deleted. It's not worth continuing. |
1006 return | 1007 return |
1007 try: | 1008 try: |
1008 SVN.Capture(['revert', file_status[1]], cwd=cwd) | 1009 SVN.Capture(['revert', file_status[1]], cwd=cwd) |
1009 except subprocess2.CalledProcessError: | 1010 except subprocess2.CalledProcessError: |
1010 if not os.path.exists(file_path): | 1011 if not os.path.exists(file_path): |
1011 continue | 1012 continue |
1012 raise | 1013 raise |
OLD | NEW |