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

Side by Side Diff: gclient_scm.py

Issue 23753008: Add json output for gclient. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix nits Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « gclient.py ('k') | tests/gclient_scm_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 """Gclient-specific SCM-specific operations.""" 5 """Gclient-specific SCM-specific operations."""
6 6
7 import collections 7 import collections
8 import logging 8 import logging
9 import os 9 import os
10 import posixpath 10 import posixpath
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 match = self.PERCENT_RE.match(line) 183 match = self.PERCENT_RE.match(line)
184 if not match: 184 if not match:
185 self.last_time = 0 185 self.last_time = 0
186 if (now - self.last_time) >= self.time_throttle: 186 if (now - self.last_time) >= self.time_throttle:
187 self.last_time = now 187 self.last_time = now
188 print line 188 print line
189 189
190 190
191 class GitWrapper(SCMWrapper): 191 class GitWrapper(SCMWrapper):
192 """Wrapper for Git""" 192 """Wrapper for Git"""
193 name = 'git'
193 194
194 cache_dir = None 195 cache_dir = None
195 # If a given cache is used in a solution more than once, prevent multiple 196 # If a given cache is used in a solution more than once, prevent multiple
196 # threads from updating it simultaneously. 197 # threads from updating it simultaneously.
197 cache_locks = collections.defaultdict(threading.Lock) 198 cache_locks = collections.defaultdict(threading.Lock)
198 199
199 def __init__(self, url=None, root_dir=None, relpath=None): 200 def __init__(self, url=None, root_dir=None, relpath=None):
200 """Removes 'git+' fake prefix from git URL.""" 201 """Removes 'git+' fake prefix from git URL."""
201 if url.startswith('git+http://') or url.startswith('git+https://'): 202 if url.startswith('git+http://') or url.startswith('git+https://'):
202 url = url[4:] 203 url = url[4:]
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 not os.path.exists(os.path.join(self.checkout_path, '.git')))): 357 not os.path.exists(os.path.join(self.checkout_path, '.git')))):
357 self._Clone(revision, url, options) 358 self._Clone(revision, url, options)
358 self.UpdateSubmoduleConfig() 359 self.UpdateSubmoduleConfig()
359 if file_list is not None: 360 if file_list is not None:
360 files = self._Capture(['ls-files']).splitlines() 361 files = self._Capture(['ls-files']).splitlines()
361 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 362 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
362 if not verbose: 363 if not verbose:
363 # Make the output a little prettier. It's nice to have some whitespace 364 # Make the output a little prettier. It's nice to have some whitespace
364 # between projects when cloning. 365 # between projects when cloning.
365 print('') 366 print('')
366 return 367 return self._Capture(['rev-parse', '--verify', 'HEAD'])
367 368
368 if not managed: 369 if not managed:
369 self._UpdateBranchHeads(options, fetch=False) 370 self._UpdateBranchHeads(options, fetch=False)
370 self.UpdateSubmoduleConfig() 371 self.UpdateSubmoduleConfig()
371 print ('________ unmanaged solution; skipping %s' % self.relpath) 372 print ('________ unmanaged solution; skipping %s' % self.relpath)
372 return 373 return self._Capture(['rev-parse', '--verify', 'HEAD'])
373 374
374 if not os.path.exists(os.path.join(self.checkout_path, '.git')): 375 if not os.path.exists(os.path.join(self.checkout_path, '.git')):
375 raise gclient_utils.Error('\n____ %s%s\n' 376 raise gclient_utils.Error('\n____ %s%s\n'
376 '\tPath is not a git repo. No .git dir.\n' 377 '\tPath is not a git repo. No .git dir.\n'
377 '\tTo resolve:\n' 378 '\tTo resolve:\n'
378 '\t\trm -rf %s\n' 379 '\t\trm -rf %s\n'
379 '\tAnd run gclient sync again\n' 380 '\tAnd run gclient sync again\n'
380 % (self.relpath, rev_str, self.relpath)) 381 % (self.relpath, rev_str, self.relpath))
381 382
382 # See if the url has changed (the unittests use git://foo for the url, let 383 # See if the url has changed (the unittests use git://foo for the url, let
(...skipping 16 matching lines...) Expand all
399 # Switch over to the new upstream 400 # Switch over to the new upstream
400 self._Run(['remote', 'set-url', 'origin', url], options) 401 self._Run(['remote', 'set-url', 'origin', url], options)
401 self._FetchAndReset(revision, file_list, options) 402 self._FetchAndReset(revision, file_list, options)
402 return_early = True 403 return_early = True
403 404
404 # Need to do this in the normal path as well as in the post-remote-switch 405 # Need to do this in the normal path as well as in the post-remote-switch
405 # path. 406 # path.
406 self._PossiblySwitchCache(url, options) 407 self._PossiblySwitchCache(url, options)
407 408
408 if return_early: 409 if return_early:
409 return 410 return self._Capture(['rev-parse', '--verify', 'HEAD'])
410 411
411 cur_branch = self._GetCurrentBranch() 412 cur_branch = self._GetCurrentBranch()
412 413
413 # Cases: 414 # Cases:
414 # 0) HEAD is detached. Probably from our initial clone. 415 # 0) HEAD is detached. Probably from our initial clone.
415 # - make sure HEAD is contained by a named ref, then update. 416 # - make sure HEAD is contained by a named ref, then update.
416 # Cases 1-4. HEAD is a branch. 417 # Cases 1-4. HEAD is a branch.
417 # 1) current branch is not tracking a remote branch (could be git-svn) 418 # 1) current branch is not tracking a remote branch (could be git-svn)
418 # - try to rebase onto the new hash or branch 419 # - try to rebase onto the new hash or branch
419 # 2) current branch is tracking a remote branch with local committed 420 # 2) current branch is tracking a remote branch with local committed
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 # 'git ls-files --directory --others --exclude-standard' here directly. 589 # 'git ls-files --directory --others --exclude-standard' here directly.
589 paths = scm.GIT.Capture( 590 paths = scm.GIT.Capture(
590 ['ls-files', '--directory', '--others', '--exclude-standard'], 591 ['ls-files', '--directory', '--others', '--exclude-standard'],
591 self.checkout_path) 592 self.checkout_path)
592 for path in (p for p in paths.splitlines() if p.endswith('/')): 593 for path in (p for p in paths.splitlines() if p.endswith('/')):
593 full_path = os.path.join(self.checkout_path, path) 594 full_path = os.path.join(self.checkout_path, path)
594 if not os.path.islink(full_path): 595 if not os.path.islink(full_path):
595 print('\n_____ removing unversioned directory %s' % path) 596 print('\n_____ removing unversioned directory %s' % path)
596 gclient_utils.rmtree(full_path) 597 gclient_utils.rmtree(full_path)
597 598
599 return self._Capture(['rev-parse', '--verify', 'HEAD'])
600
598 601
599 def revert(self, options, _args, file_list): 602 def revert(self, options, _args, file_list):
600 """Reverts local modifications. 603 """Reverts local modifications.
601 604
602 All reverted files will be appended to file_list. 605 All reverted files will be appended to file_list.
603 """ 606 """
604 if not os.path.isdir(self.checkout_path): 607 if not os.path.isdir(self.checkout_path):
605 # revert won't work if the directory doesn't exist. It needs to 608 # revert won't work if the directory doesn't exist. It needs to
606 # checkout instead. 609 # checkout instead.
607 print('\n_____ %s is missing, synching instead' % self.relpath) 610 print('\n_____ %s is missing, synching instead' % self.relpath)
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 else: 1084 else:
1082 kwargs.setdefault('print_stdout', True) 1085 kwargs.setdefault('print_stdout', True)
1083 stdout = kwargs.get('stdout', sys.stdout) 1086 stdout = kwargs.get('stdout', sys.stdout)
1084 stdout.write('\n________ running \'git %s\' in \'%s\'\n' % ( 1087 stdout.write('\n________ running \'git %s\' in \'%s\'\n' % (
1085 ' '.join(args), kwargs['cwd'])) 1088 ' '.join(args), kwargs['cwd']))
1086 gclient_utils.CheckCallAndFilter(['git'] + args, **kwargs) 1089 gclient_utils.CheckCallAndFilter(['git'] + args, **kwargs)
1087 1090
1088 1091
1089 class SVNWrapper(SCMWrapper): 1092 class SVNWrapper(SCMWrapper):
1090 """ Wrapper for SVN """ 1093 """ Wrapper for SVN """
1094 name = 'svn'
1091 1095
1092 @staticmethod 1096 @staticmethod
1093 def BinaryExists(): 1097 def BinaryExists():
1094 """Returns true if the command exists.""" 1098 """Returns true if the command exists."""
1095 try: 1099 try:
1096 result, version = scm.SVN.AssertVersion('1.4') 1100 result, version = scm.SVN.AssertVersion('1.4')
1097 if not result: 1101 if not result:
1098 raise gclient_utils.Error('SVN version is older than 1.4: %s' % version) 1102 raise gclient_utils.Error('SVN version is older than 1.4: %s' % version)
1099 return result 1103 return result
1100 except OSError: 1104 except OSError:
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 msg = ('Can\'t update/checkout %s if an unversioned directory is ' 1199 msg = ('Can\'t update/checkout %s if an unversioned directory is '
1196 'present. Delete the directory and try again.') 1200 'present. Delete the directory and try again.')
1197 raise gclient_utils.Error(msg % self.checkout_path) 1201 raise gclient_utils.Error(msg % self.checkout_path)
1198 1202
1199 if not exists: 1203 if not exists:
1200 gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path)) 1204 gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path))
1201 # We need to checkout. 1205 # We need to checkout.
1202 command = ['checkout', url, self.checkout_path] 1206 command = ['checkout', url, self.checkout_path]
1203 command = self._AddAdditionalUpdateFlags(command, options, revision) 1207 command = self._AddAdditionalUpdateFlags(command, options, revision)
1204 self._RunAndGetFileList(command, options, file_list, self._root_dir) 1208 self._RunAndGetFileList(command, options, file_list, self._root_dir)
1205 return 1209 return self.Svnversion()
1206 1210
1207 if not managed: 1211 if not managed:
1208 print ('________ unmanaged solution; skipping %s' % self.relpath) 1212 print ('________ unmanaged solution; skipping %s' % self.relpath)
1209 return 1213 return self.Svnversion()
1210 1214
1211 if 'URL' not in from_info: 1215 if 'URL' not in from_info:
1212 raise gclient_utils.Error( 1216 raise gclient_utils.Error(
1213 ('gclient is confused. Couldn\'t get the url for %s.\n' 1217 ('gclient is confused. Couldn\'t get the url for %s.\n'
1214 'Try using @unmanaged.\n%s') % ( 1218 'Try using @unmanaged.\n%s') % (
1215 self.checkout_path, from_info)) 1219 self.checkout_path, from_info))
1216 1220
1217 # Look for locked directories. 1221 # Look for locked directories.
1218 dir_info = scm.SVN.CaptureStatus( 1222 dir_info = scm.SVN.CaptureStatus(
1219 None, os.path.join(self.checkout_path, '.')) 1223 None, os.path.join(self.checkout_path, '.'))
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 ('Can\'t switch the checkout to %s; UUID don\'t match and ' 1291 ('Can\'t switch the checkout to %s; UUID don\'t match and '
1288 'there is local changes in %s. Delete the directory and ' 1292 'there is local changes in %s. Delete the directory and '
1289 'try again.') % (url, self.checkout_path)) 1293 'try again.') % (url, self.checkout_path))
1290 # Ok delete it. 1294 # Ok delete it.
1291 print('\n_____ switching %s to a new checkout' % self.relpath) 1295 print('\n_____ switching %s to a new checkout' % self.relpath)
1292 gclient_utils.rmtree(self.checkout_path) 1296 gclient_utils.rmtree(self.checkout_path)
1293 # We need to checkout. 1297 # We need to checkout.
1294 command = ['checkout', url, self.checkout_path] 1298 command = ['checkout', url, self.checkout_path]
1295 command = self._AddAdditionalUpdateFlags(command, options, revision) 1299 command = self._AddAdditionalUpdateFlags(command, options, revision)
1296 self._RunAndGetFileList(command, options, file_list, self._root_dir) 1300 self._RunAndGetFileList(command, options, file_list, self._root_dir)
1297 return 1301 return self.Svnversion()
1298 1302
1299 # If the provided url has a revision number that matches the revision 1303 # If the provided url has a revision number that matches the revision
1300 # number of the existing directory, then we don't need to bother updating. 1304 # number of the existing directory, then we don't need to bother updating.
1301 if not options.force and str(from_info['Revision']) == revision: 1305 if not options.force and str(from_info['Revision']) == revision:
1302 if options.verbose or not forced_revision: 1306 if options.verbose or not forced_revision:
1303 print('\n_____ %s%s' % (self.relpath, rev_str)) 1307 print('\n_____ %s%s' % (self.relpath, rev_str))
1304 else: 1308 else:
1305 command = ['update', self.checkout_path] 1309 command = ['update', self.checkout_path]
1306 command = self._AddAdditionalUpdateFlags(command, options, revision) 1310 command = self._AddAdditionalUpdateFlags(command, options, revision)
1307 self._RunAndGetFileList(command, options, file_list, self._root_dir) 1311 self._RunAndGetFileList(command, options, file_list, self._root_dir)
1308 1312
1309 # If --reset and --delete_unversioned_trees are specified, remove any 1313 # If --reset and --delete_unversioned_trees are specified, remove any
1310 # untracked files and directories. 1314 # untracked files and directories.
1311 if options.reset and options.delete_unversioned_trees: 1315 if options.reset and options.delete_unversioned_trees:
1312 for status in scm.SVN.CaptureStatus(None, self.checkout_path): 1316 for status in scm.SVN.CaptureStatus(None, self.checkout_path):
1313 full_path = os.path.join(self.checkout_path, status[1]) 1317 full_path = os.path.join(self.checkout_path, status[1])
1314 if (status[0][0] == '?' 1318 if (status[0][0] == '?'
1315 and os.path.isdir(full_path) 1319 and os.path.isdir(full_path)
1316 and not os.path.islink(full_path)): 1320 and not os.path.islink(full_path)):
1317 print('\n_____ removing unversioned directory %s' % status[1]) 1321 print('\n_____ removing unversioned directory %s' % status[1])
1318 gclient_utils.rmtree(full_path) 1322 gclient_utils.rmtree(full_path)
1323 return self.Svnversion()
1319 1324
1320 def updatesingle(self, options, args, file_list): 1325 def updatesingle(self, options, args, file_list):
1321 filename = args.pop() 1326 filename = args.pop()
1322 if scm.SVN.AssertVersion("1.5")[0]: 1327 if scm.SVN.AssertVersion("1.5")[0]:
1323 if not os.path.exists(os.path.join(self.checkout_path, '.svn')): 1328 if not os.path.exists(os.path.join(self.checkout_path, '.svn')):
1324 # Create an empty checkout and then update the one file we want. Future 1329 # Create an empty checkout and then update the one file we want. Future
1325 # operations will only apply to the one file we checked out. 1330 # operations will only apply to the one file we checked out.
1326 command = ["checkout", "--depth", "empty", self.url, self.checkout_path] 1331 command = ["checkout", "--depth", "empty", self.url, self.checkout_path]
1327 self._Run(command, options, cwd=self._root_dir) 1332 self._Run(command, options, cwd=self._root_dir)
1328 if os.path.exists(os.path.join(self.checkout_path, filename)): 1333 if os.path.exists(os.path.join(self.checkout_path, filename)):
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 return '/'.join(self.url.split('/')[:4]) + url 1440 return '/'.join(self.url.split('/')[:4]) + url
1436 1441
1437 def _Run(self, args, options, **kwargs): 1442 def _Run(self, args, options, **kwargs):
1438 """Runs a commands that goes to stdout.""" 1443 """Runs a commands that goes to stdout."""
1439 kwargs.setdefault('cwd', self.checkout_path) 1444 kwargs.setdefault('cwd', self.checkout_path)
1440 kwargs.setdefault('nag_timer', self.nag_timer) 1445 kwargs.setdefault('nag_timer', self.nag_timer)
1441 kwargs.setdefault('nag_max', self.nag_max) 1446 kwargs.setdefault('nag_max', self.nag_max)
1442 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, 1447 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args,
1443 always=options.verbose, **kwargs) 1448 always=options.verbose, **kwargs)
1444 1449
1450 def Svnversion(self):
1451 """Runs the lowest checked out revision in the current project."""
1452 info = scm.SVN.CaptureLocalInfo([], os.path.join(self.checkout_path, '.'))
1453 return info['Revision']
1454
1445 def _RunAndGetFileList(self, args, options, file_list, cwd=None): 1455 def _RunAndGetFileList(self, args, options, file_list, cwd=None):
1446 """Runs a commands that goes to stdout and grabs the file listed.""" 1456 """Runs a commands that goes to stdout and grabs the file listed."""
1447 cwd = cwd or self.checkout_path 1457 cwd = cwd or self.checkout_path
1448 scm.SVN.RunAndGetFileList( 1458 scm.SVN.RunAndGetFileList(
1449 options.verbose, 1459 options.verbose,
1450 args + ['--ignore-externals'], 1460 args + ['--ignore-externals'],
1451 cwd=cwd, 1461 cwd=cwd,
1452 file_list=file_list) 1462 file_list=file_list)
1453 1463
1454 @staticmethod 1464 @staticmethod
(...skipping 19 matching lines...) Expand all
1474 new_command.append('--force') 1484 new_command.append('--force')
1475 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1485 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1476 new_command.extend(('--accept', 'theirs-conflict')) 1486 new_command.extend(('--accept', 'theirs-conflict'))
1477 elif options.manually_grab_svn_rev: 1487 elif options.manually_grab_svn_rev:
1478 new_command.append('--force') 1488 new_command.append('--force')
1479 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1489 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1480 new_command.extend(('--accept', 'postpone')) 1490 new_command.extend(('--accept', 'postpone'))
1481 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1491 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1482 new_command.extend(('--accept', 'postpone')) 1492 new_command.extend(('--accept', 'postpone'))
1483 return new_command 1493 return new_command
OLDNEW
« no previous file with comments | « gclient.py ('k') | tests/gclient_scm_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698