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

Side by Side Diff: git_common.py

Issue 184253003: Add git-reup and friends (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@freeze_thaw
Patch Set: 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 MERGE_BASE_TAG_FMT = "gitscripts.merge_base_for_%s"
agable 2014/02/28 20:14:16 Ugly that some of these are using a gitscripts con
31
32
30 class DEFAULT(object): 33 class DEFAULT(object):
31 def __init__(self, constructor): 34 def __init__(self, constructor):
32 self.constructor = constructor 35 self.constructor = constructor
33 36
34 @staticmethod 37 @staticmethod
35 def get_from(inst_or_obj): 38 def get_from(inst_or_obj):
36 if isinstance(inst_or_obj, DEFAULT): 39 if isinstance(inst_or_obj, DEFAULT):
37 return inst_or_obj.constructor() 40 return inst_or_obj.constructor()
38 else: 41 else:
39 return inst_or_obj 42 return inst_or_obj
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 return run('rev-parse', '--abbrev-ref', ref) 220 return run('rev-parse', '--abbrev-ref', ref)
218 221
219 222
220 def branches(*args): 223 def branches(*args):
221 for line in run('branch', *args).splitlines(): 224 for line in run('branch', *args).splitlines():
222 if line.startswith(NO_BRANCH): 225 if line.startswith(NO_BRANCH):
223 continue 226 continue
224 yield line.split()[-1] 227 yield line.split()[-1]
225 228
226 229
230 def clean_refs():
agable 2014/02/28 20:14:16 This is really only cleaning tags, not refs...
231 run('tag', '-d',
232 *[t.strip() for t in run('tag', '-l', 'gitscripts.*').split()])
233
234
227 def config_list(option, default=DEFAULT(list)): 235 def config_list(option, default=DEFAULT(list)):
228 try: 236 try:
229 return run('config', '--get-all', option).split() 237 return run('config', '--get-all', option).split()
230 except subprocess2.CalledProcessError: 238 except subprocess2.CalledProcessError:
231 return DEFAULT.get_from(default) 239 return DEFAULT.get_from(default)
232 240
233 241
234 def current_branch(): 242 def current_branch():
235 return abbrev('HEAD') 243 return abbrev('HEAD')
236 244
237 245
238 def parse_commitrefs(*commitrefs): 246 def parse_commitrefs(*commitrefs):
239 """Returns binary encoded commit hashes for one or more commitrefs. 247 """Returns binary encoded commit hashes for one or more commitrefs.
240 248
241 A commitref is anything which can resolve to a commit. Popular examples: 249 A commitref is anything which can resolve to a commit. Popular examples:
242 * 'HEAD' 250 * 'HEAD'
243 * 'origin/master' 251 * 'origin/master'
244 * 'cool_branch~2' 252 * 'cool_branch~2'
245 """ 253 """
246 try: 254 try:
247 return map(binascii.unhexlify, hash_multi(*commitrefs)) 255 return map(binascii.unhexlify, hash_multi(*commitrefs))
248 except subprocess2.CalledProcessError: 256 except subprocess2.CalledProcessError:
249 raise BadCommitRefException(commitrefs) 257 raise BadCommitRefException(commitrefs)
250 258
251 259
260 def root():
261 return run('config', 'depot_tools.upstream') or 'origin/master'
262
263
252 def run(*cmd, **kwargs): 264 def run(*cmd, **kwargs):
253 """Runs a git command. Returns stdout as a string. 265 """Runs a git command. Returns stdout as a string.
254 266
255 If logging is DEBUG, we'll print the command before we run it. 267 If logging is DEBUG, we'll print the command before we run it.
256 268
257 kwargs 269 kwargs
258 autostrip (bool) - Strip the output. Defaults to True. 270 autostrip (bool) - Strip the output. Defaults to True.
259 """ 271 """
260 autostrip = kwargs.pop('autostrip', True) 272 autostrip = kwargs.pop('autostrip', True)
261 ret = stream(*cmd, **kwargs).read() 273 ret = stream(*cmd, **kwargs).read()
262 if autostrip: 274 if autostrip:
263 ret = (ret or '').strip() 275 ret = (ret or '').strip()
264 return ret 276 return ret
265 277
266 278
267 def stream(*cmd, **kwargs): 279 def stream(*cmd, **kwargs):
268 """Runs a git command. Returns stdout as a file. 280 """Runs a git command. Returns stdout as a file.
269 281
270 If logging is DEBUG, we'll print the command before we run it. 282 If logging is DEBUG, we'll print the command before we run it.
271 """ 283 """
272 cmd = (GIT_EXE,) + cmd 284 cmd = (GIT_EXE,) + cmd
273 logging.debug('Running %s', ' '.join(repr(tok) for tok in cmd)) 285 logging.debug('Running %s', ' '.join(repr(tok) for tok in cmd))
274 proc = subprocess2.Popen(cmd, stderr=subprocess2.VOID, 286 proc = subprocess2.Popen(cmd, stderr=subprocess2.VOID,
275 stdout=subprocess2.PIPE, **kwargs) 287 stdout=subprocess2.PIPE, **kwargs)
276 return proc.stdout 288 return proc.stdout
277 289
278 290
291 def get_or_create_merge_base_tag(branch, parent):
292 tag = MERGE_BASE_TAG_FMT % hash_one(branch)
293 tagval = None
294 try:
295 tagval = hash_one(tag)
296 logging.debug('Found tagged merge-base for %s: %s', branch, tagval)
297 except subprocess2.CalledProcessError:
298 pass
299 if not tagval:
300 run('tag', '-m', tag, tag, run('merge-base', parent, branch))
301 tagval = hash_one(tag)
302 return tagval+'^{}' # this lets rev-parse know this is actually a tag
303
304
279 def hash_one(reflike): 305 def hash_one(reflike):
280 return run('rev-parse', reflike) 306 return run('rev-parse', reflike)
281 307
282 308
283 def hash_multi(*reflike): 309 def hash_multi(*reflike):
284 return run('rev-parse', *reflike).splitlines() 310 return run('rev-parse', *reflike).splitlines()
285 311
286 312
287 def intern_f(f, kind='blob'): 313 def intern_f(f, kind='blob'):
288 """Interns a file object into the git object store. 314 """Interns a file object into the git object store.
289 315
290 Args: 316 Args:
291 f (file-like object) - The file-like object to intern 317 f (file-like object) - The file-like object to intern
292 kind (git object type) - One of 'blob', 'commit', 'tree', 'tag'. 318 kind (git object type) - One of 'blob', 'commit', 'tree', 'tag'.
293 319
294 Returns the git hash of the interned object (hex encoded). 320 Returns the git hash of the interned object (hex encoded).
295 """ 321 """
296 ret = run('hash-object', '-t', kind, '-w', '--stdin', stdin=f) 322 ret = run('hash-object', '-t', kind, '-w', '--stdin', stdin=f)
297 f.close() 323 f.close()
298 return ret 324 return ret
299 325
300 326
327 def manual_merge_base_tag(branch, base):
328 tag = MERGE_BASE_TAG_FMT % hash_one(branch)
329 run('tag', '-f', '-m', tag, tag, hash_one(base))
330
331
332 def nuke_merge_base_tag(branch):
agable 2014/02/28 20:14:16 s/nuke/remove/
333 tag = MERGE_BASE_TAG_FMT % hash_one(branch)
334 run('tag', '-d', tag)
335
336
301 def tags(*args): 337 def tags(*args):
302 for line in run('tag', *args).splitlines(): 338 for line in run('tag', *args).splitlines():
303 if line.startswith(NO_BRANCH): 339 if line.startswith(NO_BRANCH):
304 continue 340 continue
305 yield line.split()[-1] 341 yield line.split()[-1]
306 342
307 343
308 def tree(treeref, recurse=False): 344 def tree(treeref, recurse=False):
309 """Returns a dict representation of a git tree object. 345 """Returns a dict representation of a git tree object.
310 346
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 See |tree()| for the values of mode, type, and ref. 392 See |tree()| for the values of mode, type, and ref.
357 393
358 Args: 394 Args:
359 treedict - { name: (mode, type, ref) } 395 treedict - { name: (mode, type, ref) }
360 """ 396 """
361 with tempfile.TemporaryFile() as f: 397 with tempfile.TemporaryFile() as f:
362 for name, (mode, typ, ref) in treedict.iteritems(): 398 for name, (mode, typ, ref) in treedict.iteritems():
363 f.write('%s %s %s\t%s\0' % (mode, typ, ref, name)) 399 f.write('%s %s %s\t%s\0' % (mode, typ, ref, name))
364 f.seek(0) 400 f.seek(0)
365 return run('mktree', '-z', stdin=f) 401 return run('mktree', '-z', stdin=f)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698