OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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: |
OLD | NEW |