Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: git_common.py

Issue 184113002: Add git-map and git-short-map to depot_tools. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@new_branch
Patch Set: rebase and add better way to run python git extensions Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 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 # Monkeypatch IMapIterator so that Ctrl-C can kill everything properly. 5 # Monkeypatch IMapIterator so that Ctrl-C can kill everything properly.
6 # Derived from https://gist.github.com/aljungberg/626518 6 # Derived from https://gist.github.com/aljungberg/626518
7 import multiprocessing.pool 7 import multiprocessing.pool
8 from multiprocessing.pool import IMapIterator 8 from multiprocessing.pool import IMapIterator
9 def wrapper(func): 9 def wrapper(func):
10 def wrap(self, timeout=None): 10 def wrap(self, timeout=None):
11 return func(self, timeout=timeout or 1e100) 11 return func(self, timeout=timeout or 1e100)
12 return wrap 12 return wrap
13 IMapIterator.next = wrapper(IMapIterator.next) 13 IMapIterator.next = wrapper(IMapIterator.next)
14 IMapIterator.__next__ = IMapIterator.next 14 IMapIterator.__next__ = IMapIterator.next
15 # TODO(iannucci): Monkeypatch all other 'wait' methods too. 15 # TODO(iannucci): Monkeypatch all other 'wait' methods too.
16 16
17 17
18 import binascii 18 import binascii
19 import contextlib 19 import contextlib
20 import functools 20 import functools
21 import logging 21 import logging
22 import signal 22 import signal
23 import sys 23 import sys
24 import tempfile 24 import tempfile
25 import threading 25 import threading
26 26
27 import subprocess2 27 import subprocess2
28 28
29 29
30 class DEFAULT(object):
agable 2014/02/28 19:54:58 Why? This is so completely unnecessary. Maybe kind
iannucci 2014/03/06 00:18:39 *sigh* going back to useless-mode. lcd for the win
31 def __init__(self, constructor):
32 self.constructor = constructor
33
34 @staticmethod
35 def get_from(inst_or_obj):
36 if isinstance(inst_or_obj, DEFAULT):
37 return inst_or_obj.constructor()
38 else:
39 return inst_or_obj
40
41
30 GIT_EXE = 'git.bat' if sys.platform.startswith('win') else 'git' 42 GIT_EXE = 'git.bat' if sys.platform.startswith('win') else 'git'
31 43
44 NO_BRANCH = ('* (no branch)', '* (detached from ')
45
32 46
33 class BadCommitRefException(Exception): 47 class BadCommitRefException(Exception):
34 def __init__(self, refs): 48 def __init__(self, refs):
35 msg = ('one of %s does not seem to be a valid commitref.' % 49 msg = ('one of %s does not seem to be a valid commitref.' %
36 str(refs)) 50 str(refs))
37 super(BadCommitRefException, self).__init__(msg) 51 super(BadCommitRefException, self).__init__(msg)
38 52
39 53
40 def memoize_one(**kwargs): 54 def memoize_one(**kwargs):
41 """Memoizes a single-argument pure function. 55 """Memoizes a single-argument pure function.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 return self.inc 206 return self.inc
193 207
194 def __exit__(self, _exc_type, _exc_value, _traceback): 208 def __exit__(self, _exc_type, _exc_value, _traceback):
195 self._dead = True 209 self._dead = True
196 with self._dead_cond: 210 with self._dead_cond:
197 self._dead_cond.notifyAll() 211 self._dead_cond.notifyAll()
198 self._thread.join() 212 self._thread.join()
199 del self._thread 213 del self._thread
200 214
201 215
216 def abbrev(ref):
217 return run('rev-parse', '--abbrev-ref', ref)
218
219
220 def branches(*args):
221 for line in run('branch', *args).splitlines():
222 if line.startswith(NO_BRANCH):
223 continue
224 yield line.split()[-1]
225
226
227 def config_list(option, default=DEFAULT(list)):
agable 2014/02/28 19:54:58 default=None if default is None: default=[] Let's
iannucci 2014/03/06 00:18:39 sometimes I hate python. The =None idiom is so uni
agable 2014/03/06 18:09:07 I know, and I totally agree. But I don't think thi
228 try:
229 return run('config', '--get-all', option).split()
230 except subprocess2.CalledProcessError:
231 return DEFAULT.get_from(default)
232
233
234 def current_branch():
235 return abbrev('HEAD')
236
237
202 def parse_commitrefs(*commitrefs): 238 def parse_commitrefs(*commitrefs):
203 """Returns binary encoded commit hashes for one or more commitrefs. 239 """Returns binary encoded commit hashes for one or more commitrefs.
204 240
205 A commitref is anything which can resolve to a commit. Popular examples: 241 A commitref is anything which can resolve to a commit. Popular examples:
206 * 'HEAD' 242 * 'HEAD'
207 * 'origin/master' 243 * 'origin/master'
208 * 'cool_branch~2' 244 * 'cool_branch~2'
209 """ 245 """
210 try: 246 try:
211 return map(binascii.unhexlify, hashes(*commitrefs)) 247 return map(binascii.unhexlify, hash_multi(*commitrefs))
212 except subprocess2.CalledProcessError: 248 except subprocess2.CalledProcessError:
213 raise BadCommitRefException(commitrefs) 249 raise BadCommitRefException(commitrefs)
214 250
215 251
216 def run(*cmd, **kwargs): 252 def run(*cmd, **kwargs):
217 """Runs a git command. Returns stdout as a string. 253 """Runs a git command. Returns stdout as a string.
218 254
219 If logging is DEBUG, we'll print the command before we run it. 255 If logging is DEBUG, we'll print the command before we run it.
220 256
221 kwargs 257 kwargs
222 autostrip (bool) - Strip the output. Defaults to True. 258 autostrip (bool) - Strip the output. Defaults to True.
223 Output string is always strip()'d. 259 Output string is always strip()'d.
224 """ 260 """
225 autostrip = kwargs.pop('autostrip', True) 261 autostrip = kwargs.pop('autostrip', True)
226 cmd = (GIT_EXE,) + cmd 262 cmd = (GIT_EXE,) + cmd
227 logging.debug('Running %s', ' '.join(repr(tok) for tok in cmd)) 263 logging.debug('Running %s', ' '.join(repr(tok) for tok in cmd))
228 ret = subprocess2.check_output(cmd, stderr=subprocess2.PIPE, **kwargs) 264 ret = subprocess2.check_output(cmd, stderr=subprocess2.PIPE, **kwargs)
229 if autostrip: 265 if autostrip:
230 ret = (ret or '').strip() 266 ret = (ret or '').strip()
231 return ret 267 return ret
232 268
233 269
234 def hashes(*reflike): 270 def hash_one(reflike):
271 return run('rev-parse', reflike)
272
273
274 def hash_multi(*reflike):
agable 2014/02/28 19:54:58 This should be "*reflikes" (cf. "*args").
iannucci 2014/03/06 00:18:39 Done.
235 return run('rev-parse', *reflike).splitlines() 275 return run('rev-parse', *reflike).splitlines()
236 276
237 277
238 def intern_f(f, kind='blob'): 278 def intern_f(f, kind='blob'):
239 """Interns a file object into the git object store. 279 """Interns a file object into the git object store.
240 280
241 Args: 281 Args:
242 f (file-like object) - The file-like object to intern 282 f (file-like object) - The file-like object to intern
243 kind (git object type) - One of 'blob', 'commit', 'tree', 'tag'. 283 kind (git object type) - One of 'blob', 'commit', 'tree', 'tag'.
244 284
245 Returns the git hash of the interned object (hex encoded). 285 Returns the git hash of the interned object (hex encoded).
246 """ 286 """
247 ret = run('hash-object', '-t', kind, '-w', '--stdin', stdin=f) 287 ret = run('hash-object', '-t', kind, '-w', '--stdin', stdin=f)
248 f.close() 288 f.close()
249 return ret 289 return ret
250 290
251 291
292 def tags(*args):
293 for line in run('tag', *args).splitlines():
294 if line.startswith(NO_BRANCH):
295 continue
296 yield line.split()[-1]
297
298
252 def tree(treeref, recurse=False): 299 def tree(treeref, recurse=False):
253 """Returns a dict representation of a git tree object. 300 """Returns a dict representation of a git tree object.
254 301
255 Args: 302 Args:
256 treeref (str) - a git ref which resolves to a tree (commits count as trees). 303 treeref (str) - a git ref which resolves to a tree (commits count as trees).
257 recurse (bool) - include all of the tree's decendants too. File names will 304 recurse (bool) - include all of the tree's decendants too. File names will
258 take the form of 'some/path/to/file'. 305 take the form of 'some/path/to/file'.
259 306
260 Return format: 307 Return format:
261 { 'file_name': (mode, type, ref) } 308 { 'file_name': (mode, type, ref) }
(...skipping 17 matching lines...) Expand all
279 opts.append(treeref) 326 opts.append(treeref)
280 try: 327 try:
281 for line in run(*opts).splitlines(): 328 for line in run(*opts).splitlines():
282 mode, typ, ref, name = line.split(None, 3) 329 mode, typ, ref, name = line.split(None, 3)
283 ret[name] = (mode, typ, ref) 330 ret[name] = (mode, typ, ref)
284 except subprocess2.CalledProcessError: 331 except subprocess2.CalledProcessError:
285 return None 332 return None
286 return ret 333 return ret
287 334
288 335
336 def upstream(branch):
337 try:
338 return run('rev-parse', '--abbrev-ref', '--symbolic-full-name',
339 branch+'@{upstream}')
340 except subprocess2.CalledProcessError:
341 return None
342
343
289 def mktree(treedict): 344 def mktree(treedict):
290 """Makes a git tree object and returns its hash. 345 """Makes a git tree object and returns its hash.
291 346
292 See |tree()| for the values of mode, type, and ref. 347 See |tree()| for the values of mode, type, and ref.
293 348
294 Args: 349 Args:
295 treedict - { name: (mode, type, ref) } 350 treedict - { name: (mode, type, ref) }
296 """ 351 """
297 with tempfile.TemporaryFile() as f: 352 with tempfile.TemporaryFile() as f:
298 for name, (mode, typ, ref) in treedict.iteritems(): 353 for name, (mode, typ, ref) in treedict.iteritems():
299 f.write('%s %s %s\t%s\0' % (mode, typ, ref, name)) 354 f.write('%s %s %s\t%s\0' % (mode, typ, ref, name))
300 f.seek(0) 355 f.seek(0)
301 return run('mktree', '-z', stdin=f) 356 return run('mktree', '-z', stdin=f)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698