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

Side by Side Diff: gclient.py

Issue 22824018: Convert gclient to use subcommand.py (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: fix non-determinism in gclient_smoketest.py Created 7 years, 4 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 | « no previous file | git_cl.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 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Meta checkout manager supporting both Subversion and GIT. 6 """Meta checkout manager supporting both Subversion and GIT."""
7 # Files
8 # .gclient : Current client configuration, written by 'config' command.
9 # Format is a Python script defining 'solutions', a list whose
10 # entries each are maps binding the strings "name" and "url"
11 # to strings specifying the name and location of the client
12 # module, as well as "custom_deps" to a map similar to the
13 # deps section of the DEPS file below, as well as
14 # "custom_hooks" to a list similar to the hooks sections of
15 # the DEPS file below.
16 # .gclient_entries : A cache constructed by 'update' command. Format is a
17 # Python script defining 'entries', a list of the names
18 # of all modules in the client
19 # <module>/DEPS : Python script defining var 'deps' as a map from each
20 # requisite submodule name to a URL where it can be found (via
21 # one SCM)
22 #
23 # Hooks
24 # .gclient and DEPS files may optionally contain a list named "hooks" to
25 # allow custom actions to be performed based on files that have changed in the
26 # working copy as a result of a "sync"/"update" or "revert" operation. This
27 # can be prevented by using --nohooks (hooks run by default). Hooks can also
28 # be forced to run with the "runhooks" operation. If "sync" is run with
29 # --force, all known but not suppressed hooks will run regardless of the state
30 # of the working copy.
31 #
32 # Each item in a "hooks" list is a dict, containing these two keys:
33 # "pattern" The associated value is a string containing a regular
34 # expression. When a file whose pathname matches the expression
35 # is checked out, updated, or reverted, the hook's "action" will
36 # run.
37 # "action" A list describing a command to run along with its arguments, if
38 # any. An action command will run at most one time per gclient
39 # invocation, regardless of how many files matched the pattern.
40 # The action is executed in the same directory as the .gclient
41 # file. If the first item in the list is the string "python",
42 # the current Python interpreter (sys.executable) will be used
43 # to run the command. If the list contains string
44 # "$matching_files" it will be removed from the list and the list
45 # will be extended by the list of matching files.
46 # "name" An optional string specifying the group to which a hook belongs
47 # for overriding and organizing.
48 #
49 # Example:
50 # hooks = [
51 # { "pattern": "\\.(gif|jpe?g|pr0n|png)$",
52 # "action": ["python", "image_indexer.py", "--all"]},
53 # { "pattern": ".",
54 # "name": "gyp",
55 # "action": ["python", "src/build/gyp_chromium"]},
56 # ]
57 #
58 # Specifying a target OS
59 # An optional key named "target_os" may be added to a gclient file to specify
60 # one or more additional operating systems that should be considered when
61 # processing the deps_os dict of a DEPS file.
62 #
63 # Example:
64 # target_os = [ "android" ]
65 #
66 # If the "target_os_only" key is also present and true, then *only* the
67 # operating systems listed in "target_os" will be used.
68 #
69 # Example:
70 # target_os = [ "ios" ]
71 # target_os_only = True
7 72
8 Files 73 __version__ = '0.7'
9 .gclient : Current client configuration, written by 'config' command.
10 Format is a Python script defining 'solutions', a list whose
11 entries each are maps binding the strings "name" and "url"
12 to strings specifying the name and location of the client
13 module, as well as "custom_deps" to a map similar to the deps
14 section of the DEPS file below, as well as "custom_hooks" to
15 a list similar to the hooks sections of the DEPS file below.
16 .gclient_entries : A cache constructed by 'update' command. Format is a
17 Python script defining 'entries', a list of the names
18 of all modules in the client
19 <module>/DEPS : Python script defining var 'deps' as a map from each requisite
20 submodule name to a URL where it can be found (via one SCM)
21
22 Hooks
23 .gclient and DEPS files may optionally contain a list named "hooks" to
24 allow custom actions to be performed based on files that have changed in the
25 working copy as a result of a "sync"/"update" or "revert" operation. This
26 can be prevented by using --nohooks (hooks run by default). Hooks can also
27 be forced to run with the "runhooks" operation. If "sync" is run with
28 --force, all known but not suppressed hooks will run regardless of the state
29 of the working copy.
30
31 Each item in a "hooks" list is a dict, containing these two keys:
32 "pattern" The associated value is a string containing a regular
33 expression. When a file whose pathname matches the expression
34 is checked out, updated, or reverted, the hook's "action" will
35 run.
36 "action" A list describing a command to run along with its arguments, if
37 any. An action command will run at most one time per gclient
38 invocation, regardless of how many files matched the pattern.
39 The action is executed in the same directory as the .gclient
40 file. If the first item in the list is the string "python",
41 the current Python interpreter (sys.executable) will be used
42 to run the command. If the list contains string "$matching_files"
43 it will be removed from the list and the list will be extended
44 by the list of matching files.
45 "name" An optional string specifying the group to which a hook belongs
46 for overriding and organizing.
47
48 Example:
49 hooks = [
50 { "pattern": "\\.(gif|jpe?g|pr0n|png)$",
51 "action": ["python", "image_indexer.py", "--all"]},
52 { "pattern": ".",
53 "name": "gyp",
54 "action": ["python", "src/build/gyp_chromium"]},
55 ]
56
57 Specifying a target OS
58 An optional key named "target_os" may be added to a gclient file to specify
59 one or more additional operating systems that should be considered when
60 processing the deps_os dict of a DEPS file.
61
62 Example:
63 target_os = [ "android" ]
64
65 If the "target_os_only" key is also present and true, then *only* the
66 operating systems listed in "target_os" will be used.
67
68 Example:
69 target_os = [ "ios" ]
70 target_os_only = True
71 """
72
73 __version__ = "0.6.4"
74 74
75 import copy 75 import copy
76 import logging 76 import logging
77 import optparse 77 import optparse
78 import os 78 import os
79 import platform 79 import platform
80 import posixpath 80 import posixpath
81 import pprint 81 import pprint
82 import re 82 import re
83 import sys 83 import sys
84 import time 84 import time
85 import urllib 85 import urllib
86 import urlparse 86 import urlparse
87 87
88 import breakpad # pylint: disable=W0611 88 import breakpad # pylint: disable=W0611
89 89
90 import fix_encoding 90 import fix_encoding
91 import gclient_scm 91 import gclient_scm
92 import gclient_utils 92 import gclient_utils
93 from third_party.repo.progress import Progress 93 from third_party.repo.progress import Progress
94 import subcommand
94 import subprocess2 95 import subprocess2
95 from third_party import colorama 96 from third_party import colorama
96 # Import shortcut.
97 from third_party.colorama import Fore
98
99
100 def attr(attribute, data):
101 """Sets an attribute on a function."""
102 def hook(fn):
103 setattr(fn, attribute, data)
104 return fn
105 return hook
106
107
108 ## GClient implementation.
109 97
110 98
111 class GClientKeywords(object): 99 class GClientKeywords(object):
112 class FromImpl(object): 100 class FromImpl(object):
113 """Used to implement the From() syntax.""" 101 """Used to implement the From() syntax."""
114 102
115 def __init__(self, module_name, sub_target_name=None): 103 def __init__(self, module_name, sub_target_name=None):
116 """module_name is the dep module we want to include from. It can also be 104 """module_name is the dep module we want to include from. It can also be
117 the name of a subdirectory to include from. 105 the name of a subdirectory to include from.
118 106
(...skipping 1188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 def target_os(self): 1295 def target_os(self):
1308 return self._enforced_os 1296 return self._enforced_os
1309 1297
1310 1298
1311 #### gclient commands. 1299 #### gclient commands.
1312 1300
1313 1301
1314 def CMDcleanup(parser, args): 1302 def CMDcleanup(parser, args):
1315 """Cleans up all working copies. 1303 """Cleans up all working copies.
1316 1304
1317 Mostly svn-specific. Simply runs 'svn cleanup' for each module. 1305 Mostly svn-specific. Simply runs 'svn cleanup' for each module.
1318 """ 1306 """
1319 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1307 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1320 help='override deps for the specified (comma-separated) ' 1308 help='override deps for the specified (comma-separated) '
1321 'platform(s); \'all\' will process all deps_os ' 1309 'platform(s); \'all\' will process all deps_os '
1322 'references') 1310 'references')
1323 (options, args) = parser.parse_args(args) 1311 (options, args) = parser.parse_args(args)
1324 client = GClient.LoadCurrentConfig(options) 1312 client = GClient.LoadCurrentConfig(options)
1325 if not client: 1313 if not client:
1326 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1314 raise gclient_utils.Error('client not configured; see \'gclient config\'')
1327 if options.verbose: 1315 if options.verbose:
1328 # Print out the .gclient file. This is longer than if we just printed the 1316 # Print out the .gclient file. This is longer than if we just printed the
1329 # client dict, but more legible, and it might contain helpful comments. 1317 # client dict, but more legible, and it might contain helpful comments.
1330 print(client.config_content) 1318 print(client.config_content)
1331 return client.RunOnDeps('cleanup', args) 1319 return client.RunOnDeps('cleanup', args)
1332 1320
1333 1321
1334 @attr('usage', '[command] [args ...]') 1322 @subcommand.usage('[command] [args ...]')
1335 def CMDrecurse(parser, args): 1323 def CMDrecurse(parser, args):
1336 """Operates on all the entries. 1324 """Operates [command args ...] on all the dependencies.
1337 1325
1338 Runs a shell command on all entries. 1326 Runs a shell command on all entries.
1339 Sets GCLIENT_DEP_PATH enviroment variable as the dep's relative location to 1327 Sets GCLIENT_DEP_PATH enviroment variable as the dep's relative location to
1340 root directory of the checkout. 1328 root directory of the checkout.
1341 """ 1329 """
1342 # Stop parsing at the first non-arg so that these go through to the command 1330 # Stop parsing at the first non-arg so that these go through to the command
1343 parser.disable_interspersed_args() 1331 parser.disable_interspersed_args()
1344 parser.add_option('-s', '--scm', action='append', default=[], 1332 parser.add_option('-s', '--scm', action='append', default=[],
1345 help='Choose scm types to operate upon.') 1333 help='Choose scm types to operate upon.')
1346 parser.add_option('-i', '--ignore', action='store_true', 1334 parser.add_option('-i', '--ignore', action='store_true',
(...skipping 18 matching lines...) Expand all
1365 for scm in options.scm: 1353 for scm in options.scm:
1366 scm_set.update(scm.split(',')) 1354 scm_set.update(scm.split(','))
1367 options.scm = scm_set 1355 options.scm = scm_set
1368 1356
1369 options.nohooks = True 1357 options.nohooks = True
1370 client = GClient.LoadCurrentConfig(options) 1358 client = GClient.LoadCurrentConfig(options)
1371 return client.RunOnDeps('recurse', args, ignore_requirements=True, 1359 return client.RunOnDeps('recurse', args, ignore_requirements=True,
1372 progress=not options.no_progress) 1360 progress=not options.no_progress)
1373 1361
1374 1362
1375 @attr('usage', '[args ...]') 1363 @subcommand.usage('[args ...]')
1376 def CMDfetch(parser, args): 1364 def CMDfetch(parser, args):
1377 """Fetches upstream commits for all modules. 1365 """Fetches upstream commits for all modules.
1378 1366
1379 Completely git-specific. Simply runs 'git fetch [args ...]' for each module. 1367 Completely git-specific. Simply runs 'git fetch [args ...]' for each module.
1380 """ 1368 """
1381 (options, args) = parser.parse_args(args) 1369 (options, args) = parser.parse_args(args)
1382 return CMDrecurse(OptionParser(), [ 1370 return CMDrecurse(OptionParser(), [
1383 '--jobs=%d' % options.jobs, '--scm=git', 'git', 'fetch'] + args) 1371 '--jobs=%d' % options.jobs, '--scm=git', 'git', 'fetch'] + args)
1384 1372
1385 1373
1386 def CMDgrep(parser, args): 1374 def CMDgrep(parser, args):
1387 """Greps through git repos managed by gclient. 1375 """Greps through git repos managed by gclient.
1388 1376
1389 Runs 'git grep [args...]' for each module. 1377 Runs 'git grep [args...]' for each module.
1390 """ 1378 """
1391
1392 # We can't use optparse because it will try to parse arguments sent 1379 # We can't use optparse because it will try to parse arguments sent
1393 # to git grep and throw an error. :-( 1380 # to git grep and throw an error. :-(
1394 if not args or re.match('(-h|--help)$', args[0]): 1381 if not args or re.match('(-h|--help)$', args[0]):
1395 print >> sys.stderr, ( 1382 print >> sys.stderr, (
1396 'Usage: gclient grep [-j <N>] git-grep-args...\n\n' 1383 'Usage: gclient grep [-j <N>] git-grep-args...\n\n'
1397 'Example: "gclient grep -j10 -A2 RefCountedBase" runs\n"git grep ' 1384 'Example: "gclient grep -j10 -A2 RefCountedBase" runs\n"git grep '
1398 '-A2 RefCountedBase" on each of gclient\'s git\nrepos with up to ' 1385 '-A2 RefCountedBase" on each of gclient\'s git\nrepos with up to '
1399 '10 jobs.\n\nBonus: page output by appending "|& less -FRSX" to the' 1386 '10 jobs.\n\nBonus: page output by appending "|& less -FRSX" to the'
1400 ' end of your query.' 1387 ' end of your query.'
1401 ) 1388 )
1402 return 1 1389 return 1
1403 1390
1404 jobs_arg = ['--jobs=1'] 1391 jobs_arg = ['--jobs=1']
1405 if re.match(r'(-j|--jobs=)\d+$', args[0]): 1392 if re.match(r'(-j|--jobs=)\d+$', args[0]):
1406 jobs_arg, args = args[:1], args[1:] 1393 jobs_arg, args = args[:1], args[1:]
1407 elif re.match(r'(-j|--jobs)$', args[0]): 1394 elif re.match(r'(-j|--jobs)$', args[0]):
1408 jobs_arg, args = args[:2], args[2:] 1395 jobs_arg, args = args[:2], args[2:]
1409 1396
1410 return CMDrecurse( 1397 return CMDrecurse(
1411 parser, 1398 parser,
1412 jobs_arg + ['--ignore', '--prepend-dir', '--no-progress', '--scm=git', 1399 jobs_arg + ['--ignore', '--prepend-dir', '--no-progress', '--scm=git',
1413 'git', 'grep', '--null', '--color=Always'] + args) 1400 'git', 'grep', '--null', '--color=Always'] + args)
1414 1401
1415 1402
1416 @attr('usage', '[url] [safesync url]') 1403 @subcommand.usage('[url] [safesync url]')
1417 def CMDconfig(parser, args): 1404 def CMDconfig(parser, args):
1418 """Create a .gclient file in the current directory. 1405 """Creates a .gclient file in the current directory.
1419 1406
1420 This specifies the configuration for further commands. After update/sync, 1407 This specifies the configuration for further commands. After update/sync,
1421 top-level DEPS files in each module are read to determine dependent 1408 top-level DEPS files in each module are read to determine dependent
1422 modules to operate on as well. If optional [url] parameter is 1409 modules to operate on as well. If optional [url] parameter is
1423 provided, then configuration is read from a specified Subversion server 1410 provided, then configuration is read from a specified Subversion server
1424 URL. 1411 URL.
1425 """ 1412 """
1426
1427 # We do a little dance with the --gclientfile option. 'gclient config' is the 1413 # We do a little dance with the --gclientfile option. 'gclient config' is the
1428 # only command where it's acceptable to have both '--gclientfile' and '--spec' 1414 # only command where it's acceptable to have both '--gclientfile' and '--spec'
1429 # arguments. So, we temporarily stash any --gclientfile parameter into 1415 # arguments. So, we temporarily stash any --gclientfile parameter into
1430 # options.output_config_file until after the (gclientfile xor spec) error 1416 # options.output_config_file until after the (gclientfile xor spec) error
1431 # check. 1417 # check.
1432 parser.remove_option('--gclientfile') 1418 parser.remove_option('--gclientfile')
1433 parser.add_option('--gclientfile', dest='output_config_file', 1419 parser.add_option('--gclientfile', dest='output_config_file',
1434 help='Specify an alternate .gclient file') 1420 help='Specify an alternate .gclient file')
1435 parser.add_option('--name', 1421 parser.add_option('--name',
1436 help='overrides the default name for the solution') 1422 help='overrides the default name for the solution')
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 safesync_url = '' 1460 safesync_url = ''
1475 if len(args) > 1: 1461 if len(args) > 1:
1476 safesync_url = args[1] 1462 safesync_url = args[1]
1477 client.SetDefaultConfig(name, deps_file, base_url, safesync_url, 1463 client.SetDefaultConfig(name, deps_file, base_url, safesync_url,
1478 managed=not options.unmanaged, 1464 managed=not options.unmanaged,
1479 cache_dir=options.cache_dir) 1465 cache_dir=options.cache_dir)
1480 client.SaveConfig() 1466 client.SaveConfig()
1481 return 0 1467 return 0
1482 1468
1483 1469
1484 @attr('epilog', """Example: 1470 @subcommand.epilog("""Example:
1485 gclient pack > patch.txt 1471 gclient pack > patch.txt
1486 generate simple patch for configured client and dependences 1472 generate simple patch for configured client and dependences
1487 """) 1473 """)
1488 def CMDpack(parser, args): 1474 def CMDpack(parser, args):
1489 """Generate a patch which can be applied at the root of the tree. 1475 """Generates a patch which can be applied at the root of the tree.
1490 1476
1491 Internally, runs 'svn diff'/'git diff' on each checked out module and 1477 Internally, runs 'svn diff'/'git diff' on each checked out module and
1492 dependencies, and performs minimal postprocessing of the output. The 1478 dependencies, and performs minimal postprocessing of the output. The
1493 resulting patch is printed to stdout and can be applied to a freshly 1479 resulting patch is printed to stdout and can be applied to a freshly
1494 checked out tree via 'patch -p0 < patchfile'. 1480 checked out tree via 'patch -p0 < patchfile'.
1495 """ 1481 """
1496 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1482 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1497 help='override deps for the specified (comma-separated) ' 1483 help='override deps for the specified (comma-separated) '
1498 'platform(s); \'all\' will process all deps_os ' 1484 'platform(s); \'all\' will process all deps_os '
1499 'references') 1485 'references')
1500 parser.remove_option('--jobs') 1486 parser.remove_option('--jobs')
1501 (options, args) = parser.parse_args(args) 1487 (options, args) = parser.parse_args(args)
1502 # Force jobs to 1 so the stdout is not annotated with the thread ids 1488 # Force jobs to 1 so the stdout is not annotated with the thread ids
1503 options.jobs = 1 1489 options.jobs = 1
1504 client = GClient.LoadCurrentConfig(options) 1490 client = GClient.LoadCurrentConfig(options)
1505 if not client: 1491 if not client:
1506 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1492 raise gclient_utils.Error('client not configured; see \'gclient config\'')
1507 if options.verbose: 1493 if options.verbose:
1508 # Print out the .gclient file. This is longer than if we just printed the 1494 # Print out the .gclient file. This is longer than if we just printed the
1509 # client dict, but more legible, and it might contain helpful comments. 1495 # client dict, but more legible, and it might contain helpful comments.
1510 print(client.config_content) 1496 print(client.config_content)
1511 return client.RunOnDeps('pack', args) 1497 return client.RunOnDeps('pack', args)
1512 1498
1513 1499
1514 def CMDstatus(parser, args): 1500 def CMDstatus(parser, args):
1515 """Show modification status for every dependencies.""" 1501 """Shows modification status for every dependencies."""
1516 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1502 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1517 help='override deps for the specified (comma-separated) ' 1503 help='override deps for the specified (comma-separated) '
1518 'platform(s); \'all\' will process all deps_os ' 1504 'platform(s); \'all\' will process all deps_os '
1519 'references') 1505 'references')
1520 (options, args) = parser.parse_args(args) 1506 (options, args) = parser.parse_args(args)
1521 client = GClient.LoadCurrentConfig(options) 1507 client = GClient.LoadCurrentConfig(options)
1522 if not client: 1508 if not client:
1523 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1509 raise gclient_utils.Error('client not configured; see \'gclient config\'')
1524 if options.verbose: 1510 if options.verbose:
1525 # Print out the .gclient file. This is longer than if we just printed the 1511 # Print out the .gclient file. This is longer than if we just printed the
1526 # client dict, but more legible, and it might contain helpful comments. 1512 # client dict, but more legible, and it might contain helpful comments.
1527 print(client.config_content) 1513 print(client.config_content)
1528 return client.RunOnDeps('status', args) 1514 return client.RunOnDeps('status', args)
1529 1515
1530 1516
1531 @attr('epilog', """Examples: 1517 @subcommand.epilog("""Examples:
1532 gclient sync 1518 gclient sync
1533 update files from SCM according to current configuration, 1519 update files from SCM according to current configuration,
1534 *for modules which have changed since last update or sync* 1520 *for modules which have changed since last update or sync*
1535 gclient sync --force 1521 gclient sync --force
1536 update files from SCM according to current configuration, for 1522 update files from SCM according to current configuration, for
1537 all modules (useful for recovering files deleted from local copy) 1523 all modules (useful for recovering files deleted from local copy)
1538 gclient sync --revision src@31000 1524 gclient sync --revision src@31000
1539 update src directory to r31000 1525 update src directory to r31000
1540 """) 1526 """)
1541 def CMDsync(parser, args): 1527 def CMDsync(parser, args):
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 # TODO(maruel): Make it a parser.error if it doesn't break any builder. 1583 # TODO(maruel): Make it a parser.error if it doesn't break any builder.
1598 print('Warning: you cannot use both --head and --revision') 1584 print('Warning: you cannot use both --head and --revision')
1599 1585
1600 if options.verbose: 1586 if options.verbose:
1601 # Print out the .gclient file. This is longer than if we just printed the 1587 # Print out the .gclient file. This is longer than if we just printed the
1602 # client dict, but more legible, and it might contain helpful comments. 1588 # client dict, but more legible, and it might contain helpful comments.
1603 print(client.config_content) 1589 print(client.config_content)
1604 return client.RunOnDeps('update', args) 1590 return client.RunOnDeps('update', args)
1605 1591
1606 1592
1607 def CMDupdate(parser, args): 1593 CMDupdate = CMDsync
1608 """Alias for the sync command. Deprecated.""" 1594
1609 return CMDsync(parser, args)
1610 1595
1611 def CMDdiff(parser, args): 1596 def CMDdiff(parser, args):
1612 """Displays local diff for every dependencies.""" 1597 """Displays local diff for every dependencies."""
1613 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1598 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1614 help='override deps for the specified (comma-separated) ' 1599 help='override deps for the specified (comma-separated) '
1615 'platform(s); \'all\' will process all deps_os ' 1600 'platform(s); \'all\' will process all deps_os '
1616 'references') 1601 'references')
1617 (options, args) = parser.parse_args(args) 1602 (options, args) = parser.parse_args(args)
1618 client = GClient.LoadCurrentConfig(options) 1603 client = GClient.LoadCurrentConfig(options)
1619 if not client: 1604 if not client:
1620 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1605 raise gclient_utils.Error('client not configured; see \'gclient config\'')
1621 if options.verbose: 1606 if options.verbose:
1622 # Print out the .gclient file. This is longer than if we just printed the 1607 # Print out the .gclient file. This is longer than if we just printed the
1623 # client dict, but more legible, and it might contain helpful comments. 1608 # client dict, but more legible, and it might contain helpful comments.
1624 print(client.config_content) 1609 print(client.config_content)
1625 return client.RunOnDeps('diff', args) 1610 return client.RunOnDeps('diff', args)
1626 1611
1627 1612
1628 def CMDrevert(parser, args): 1613 def CMDrevert(parser, args):
1629 """Revert all modifications in every dependencies. 1614 """Reverts all modifications in every dependencies.
1630 1615
1631 That's the nuclear option to get back to a 'clean' state. It removes anything 1616 That's the nuclear option to get back to a 'clean' state. It removes anything
1632 that shows up in svn status.""" 1617 that shows up in svn status."""
1633 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1618 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1634 help='override deps for the specified (comma-separated) ' 1619 help='override deps for the specified (comma-separated) '
1635 'platform(s); \'all\' will process all deps_os ' 1620 'platform(s); \'all\' will process all deps_os '
1636 'references') 1621 'references')
1637 parser.add_option('-n', '--nohooks', action='store_true', 1622 parser.add_option('-n', '--nohooks', action='store_true',
1638 help='don\'t run hooks after the revert is complete') 1623 help='don\'t run hooks after the revert is complete')
1639 parser.add_option('--upstream', action='store_true', 1624 parser.add_option('--upstream', action='store_true',
(...skipping 24 matching lines...) Expand all
1664 if options.verbose: 1649 if options.verbose:
1665 # Print out the .gclient file. This is longer than if we just printed the 1650 # Print out the .gclient file. This is longer than if we just printed the
1666 # client dict, but more legible, and it might contain helpful comments. 1651 # client dict, but more legible, and it might contain helpful comments.
1667 print(client.config_content) 1652 print(client.config_content)
1668 options.force = True 1653 options.force = True
1669 options.nohooks = False 1654 options.nohooks = False
1670 return client.RunOnDeps('runhooks', args) 1655 return client.RunOnDeps('runhooks', args)
1671 1656
1672 1657
1673 def CMDrevinfo(parser, args): 1658 def CMDrevinfo(parser, args):
1674 """Output revision info mapping for the client and its dependencies. 1659 """Outputs revision info mapping for the client and its dependencies.
1675 1660
1676 This allows the capture of an overall 'revision' for the source tree that 1661 This allows the capture of an overall 'revision' for the source tree that
1677 can be used to reproduce the same tree in the future. It is only useful for 1662 can be used to reproduce the same tree in the future. It is only useful for
1678 'unpinned dependencies', i.e. DEPS/deps references without a svn revision 1663 'unpinned dependencies', i.e. DEPS/deps references without a svn revision
1679 number or a git hash. A git branch name isn't 'pinned' since the actual 1664 number or a git hash. A git branch name isn't 'pinned' since the actual
1680 commit can change. 1665 commit can change.
1681 """ 1666 """
1682 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1667 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1683 help='override deps for the specified (comma-separated) ' 1668 help='override deps for the specified (comma-separated) '
1684 'platform(s); \'all\' will process all deps_os ' 1669 'platform(s); \'all\' will process all deps_os '
1685 'references') 1670 'references')
1686 parser.add_option('-a', '--actual', action='store_true', 1671 parser.add_option('-a', '--actual', action='store_true',
1687 help='gets the actual checked out revisions instead of the ' 1672 help='gets the actual checked out revisions instead of the '
1688 'ones specified in the DEPS and .gclient files') 1673 'ones specified in the DEPS and .gclient files')
1689 parser.add_option('-s', '--snapshot', action='store_true', 1674 parser.add_option('-s', '--snapshot', action='store_true',
1690 help='creates a snapshot .gclient file of the current ' 1675 help='creates a snapshot .gclient file of the current '
1691 'version of all repositories to reproduce the tree, ' 1676 'version of all repositories to reproduce the tree, '
1692 'implies -a') 1677 'implies -a')
1693 (options, args) = parser.parse_args(args) 1678 (options, args) = parser.parse_args(args)
1694 client = GClient.LoadCurrentConfig(options) 1679 client = GClient.LoadCurrentConfig(options)
1695 if not client: 1680 if not client:
1696 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1681 raise gclient_utils.Error('client not configured; see \'gclient config\'')
1697 client.PrintRevInfo() 1682 client.PrintRevInfo()
1698 return 0 1683 return 0
1699 1684
1700 1685
1701 def CMDhookinfo(parser, args): 1686 def CMDhookinfo(parser, args):
1702 """Output the hooks that would be run by `gclient runhooks`""" 1687 """Outputs the hooks that would be run by `gclient runhooks`."""
1703 (options, args) = parser.parse_args(args) 1688 (options, args) = parser.parse_args(args)
1704 options.force = True 1689 options.force = True
1705 client = GClient.LoadCurrentConfig(options) 1690 client = GClient.LoadCurrentConfig(options)
1706 if not client: 1691 if not client:
1707 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1692 raise gclient_utils.Error('client not configured; see \'gclient config\'')
1708 client.RunOnDeps(None, []) 1693 client.RunOnDeps(None, [])
1709 print '; '.join(' '.join(hook) for hook in client.GetHooks(options)) 1694 print '; '.join(' '.join(hook) for hook in client.GetHooks(options))
1710 return 0 1695 return 0
1711 1696
1712 1697
1713 def Command(name):
1714 return getattr(sys.modules[__name__], 'CMD' + name, None)
1715
1716
1717 def CMDhelp(parser, args):
1718 """Prints list of commands or help for a specific command."""
1719 (_, args) = parser.parse_args(args)
1720 if len(args) == 1:
1721 return Main(args + ['--help'])
1722 parser.print_help()
1723 return 0
1724
1725
1726 def GenUsage(parser, command):
1727 """Modify an OptParse object with the function's documentation."""
1728 obj = Command(command)
1729 if command == 'help':
1730 command = '<command>'
1731 # OptParser.description prefer nicely non-formatted strings.
1732 parser.description = re.sub('[\r\n ]{2,}', ' ', obj.__doc__)
1733 usage = getattr(obj, 'usage', '')
1734 parser.set_usage('%%prog %s [options] %s' % (command, usage))
1735 parser.epilog = getattr(obj, 'epilog', None)
1736
1737
1738 class OptionParser(optparse.OptionParser): 1698 class OptionParser(optparse.OptionParser):
1739 gclientfile_default = os.environ.get('GCLIENT_FILE', '.gclient') 1699 gclientfile_default = os.environ.get('GCLIENT_FILE', '.gclient')
1740 1700
1741 def __init__(self, **kwargs): 1701 def __init__(self, **kwargs):
1742 optparse.OptionParser.__init__( 1702 optparse.OptionParser.__init__(
1743 self, version='%prog ' + __version__, **kwargs) 1703 self, version='%prog ' + __version__, **kwargs)
1744 1704
1745 # Some arm boards have issues with parallel sync. 1705 # Some arm boards have issues with parallel sync.
1746 if platform.machine().startswith('arm'): 1706 if platform.machine().startswith('arm'):
1747 jobs = 1 1707 jobs = 1
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1798 if not hasattr(options, 'deps_os'): 1758 if not hasattr(options, 'deps_os'):
1799 options.deps_os = None 1759 options.deps_os = None
1800 if not hasattr(options, 'manually_grab_svn_rev'): 1760 if not hasattr(options, 'manually_grab_svn_rev'):
1801 options.manually_grab_svn_rev = None 1761 options.manually_grab_svn_rev = None
1802 if not hasattr(options, 'force'): 1762 if not hasattr(options, 'force'):
1803 options.force = None 1763 options.force = None
1804 if options.no_nag_max: 1764 if options.no_nag_max:
1805 gclient_scm.SCMWrapper.nag_max = None 1765 gclient_scm.SCMWrapper.nag_max = None
1806 return (options, args) 1766 return (options, args)
1807 1767
1808 def format_epilog(self, _): 1768
1809 """Disables wordwrapping in epilog (usually examples).""" 1769 def disable_buffering():
1810 return self.epilog or '' 1770 # Make stdout auto-flush so buildbot doesn't kill us during lengthy
1771 # operations. Python as a strong tendency to buffer sys.stdout.
1772 sys.stdout = gclient_utils.MakeFileAutoFlush(sys.stdout)
1773 # Make stdout annotated with the thread ids.
1774 sys.stdout = gclient_utils.MakeFileAnnotated(sys.stdout)
1811 1775
1812 1776
1813 def Main(argv): 1777 def Main(argv):
1814 """Doesn't parse the arguments here, just find the right subcommand to 1778 """Doesn't parse the arguments here, just find the right subcommand to
1815 execute.""" 1779 execute."""
1816 if sys.hexversion < 0x02060000: 1780 if sys.hexversion < 0x02060000:
1817 print >> sys.stderr, ( 1781 print >> sys.stderr, (
1818 '\nYour python version %s is unsupported, please upgrade.\n' % 1782 '\nYour python version %s is unsupported, please upgrade.\n' %
1819 sys.version.split(' ', 1)[0]) 1783 sys.version.split(' ', 1)[0])
1820 return 2 1784 return 2
1821 if not sys.executable: 1785 if not sys.executable:
1822 print >> sys.stderr, ( 1786 print >> sys.stderr, (
1823 '\nPython cannot find the location of it\'s own executable.\n') 1787 '\nPython cannot find the location of it\'s own executable.\n')
1824 return 2 1788 return 2
1789 fix_encoding.fix_encoding()
1790 disable_buffering()
1825 colorama.init() 1791 colorama.init()
1792 dispatcher = subcommand.CommandDispatcher(__name__)
1826 try: 1793 try:
1827 # Make stdout auto-flush so buildbot doesn't kill us during lengthy 1794 return dispatcher.execute(OptionParser(), argv)
1828 # operations. Python as a strong tendency to buffer sys.stdout.
1829 sys.stdout = gclient_utils.MakeFileAutoFlush(sys.stdout)
1830 # Make stdout annotated with the thread ids.
1831 sys.stdout = gclient_utils.MakeFileAnnotated(sys.stdout)
1832 # Do it late so all commands are listed.
1833 # Unused variable 'usage'
1834 # pylint: disable=W0612
1835 def to_str(fn):
1836 return (
1837 ' %s%-10s%s' % (Fore.GREEN, fn[3:], Fore.RESET) +
1838 ' %s' % Command(fn[3:]).__doc__.split('\n')[0].strip())
1839 cmds = (
1840 to_str(fn) for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')
1841 )
1842 CMDhelp.usage = '\n\nCommands are:\n' + '\n'.join(cmds)
1843 parser = OptionParser()
1844 if argv:
1845 command = Command(argv[0])
1846 if command:
1847 # 'fix' the usage and the description now that we know the subcommand.
1848 GenUsage(parser, argv[0])
1849 return command(parser, argv[1:])
1850 # Not a known command. Default to help.
1851 GenUsage(parser, 'help')
1852 return CMDhelp(parser, argv)
1853 except KeyboardInterrupt: 1795 except KeyboardInterrupt:
1854 gclient_utils.GClientChildren.KillAllRemainingChildren() 1796 gclient_utils.GClientChildren.KillAllRemainingChildren()
1855 raise 1797 raise
1856 except (gclient_utils.Error, subprocess2.CalledProcessError), e: 1798 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
1857 print >> sys.stderr, 'Error: %s' % str(e) 1799 print >> sys.stderr, 'Error: %s' % str(e)
1858 return 1 1800 return 1
1859 1801
1860 1802
1861 if '__main__' == __name__: 1803 if '__main__' == __name__:
1862 fix_encoding.fix_encoding()
1863 sys.exit(Main(sys.argv[1:])) 1804 sys.exit(Main(sys.argv[1:]))
1864 1805
1865 # vim: ts=2:sw=2:tw=80:et: 1806 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | git_cl.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698