Skip to content

Commit b2f3ae8

Browse files
authored
Merge pull request #83 from jedwards4b/jedwards/components_arg
add a components arg to checkout only select components Add optional argument to only process components listed on the command line checkout_externals cam clm will only process externals associated with the listed components cam and clm. Also added a test of the new functionality. User interface changes?: Yes An additional command line option was added, previous functionality continues to be supported Fixes: #80 Testing: test removed: unit tests: all pass system tests: manual testing: Tested with lists of components in Externals.cfg and with ones that were not there.
2 parents 6923119 + 3f4c88f commit b2f3ae8

File tree

4 files changed

+75
-12
lines changed

4 files changed

+75
-12
lines changed

manic/checkout.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from manic.externals_description import read_externals_description_file
2121
from manic.externals_status import check_safe_to_update_repos
2222
from manic.sourcetree import SourceTree
23-
from manic.utils import printlog
23+
from manic.utils import printlog, fatal_error
2424
from manic.global_constants import VERSION_SEPERATOR, LOG_FILE_NAME
2525

2626
if sys.hexversion < 0x02070000:
@@ -243,6 +243,10 @@ def commandline_arguments(args=None):
243243
#
244244
# user options
245245
#
246+
parser.add_argument("components", nargs="*",
247+
help="Specific component(s) to checkout. By default"
248+
"all required externals are checked out.")
249+
246250
parser.add_argument('-e', '--externals', nargs='?',
247251
default='Externals.cfg',
248252
help='The externals description filename. '
@@ -316,7 +320,12 @@ def main(args):
316320

317321
root_dir = os.path.abspath(os.getcwd())
318322
external_data = read_externals_description_file(root_dir, args.externals)
319-
external = create_externals_description(external_data)
323+
external = create_externals_description(external_data, components=args.components)
324+
325+
for comp in args.components:
326+
if comp not in external.keys():
327+
fatal_error("No component {} found in {}".format(comp, args.externals))
328+
320329

321330
source_tree = SourceTree(root_dir, external)
322331
printlog('Checking status of externals: ', end='')
@@ -354,7 +363,10 @@ def main(args):
354363
printlog(msg)
355364
printlog('-' * 70)
356365
else:
357-
source_tree.checkout(args.verbose, load_all)
366+
if not args.components:
367+
source_tree.checkout(args.verbose, load_all)
368+
for comp in args.components:
369+
source_tree.checkout(args.verbose, load_all, load_comp=comp)
358370
printlog('')
359371

360372
logging.info('%s completed without exceptions.', program_name)

manic/externals_description.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,16 @@ def read_externals_description_file(root_dir, file_name):
9191
return externals_description
9292

9393

94-
def create_externals_description(model_data, model_format='cfg'):
94+
def create_externals_description(model_data, model_format='cfg', components=None):
9595
"""Create the a externals description object from the provided data
9696
"""
9797
externals_description = None
9898
if model_format == 'dict':
99-
externals_description = ExternalsDescriptionDict(model_data, )
99+
externals_description = ExternalsDescriptionDict(model_data, components=components)
100100
elif model_format == 'cfg':
101101
major, _, _ = get_cfg_schema_version(model_data)
102102
if major == 1:
103-
externals_description = ExternalsDescriptionConfigV1(model_data)
103+
externals_description = ExternalsDescriptionConfigV1(model_data, components=components)
104104
else:
105105
msg = ('Externals description file has unsupported schema '
106106
'version "{0}".'.format(major))
@@ -419,7 +419,7 @@ class ExternalsDescriptionDict(ExternalsDescription):
419419
420420
"""
421421

422-
def __init__(self, model_data):
422+
def __init__(self, model_data, components=None):
423423
"""Parse a native dictionary into a externals description.
424424
"""
425425
ExternalsDescription.__init__(self)
@@ -430,6 +430,11 @@ def __init__(self, model_data):
430430
self._input_minor = 0
431431
self._input_patch = 0
432432
self._verify_schema_version()
433+
if components:
434+
for k in model_data.items():
435+
if k not in components:
436+
del model_data[k]
437+
433438
self.update(model_data)
434439
self._check_user_input()
435440

@@ -440,8 +445,8 @@ class ExternalsDescriptionConfigV1(ExternalsDescription):
440445
441446
"""
442447

443-
def __init__(self, model_data):
444-
"""Convert the xml into a standardized dict that can be used to
448+
def __init__(self, model_data, components=None):
449+
"""Convert the config data into a standardized dict that can be used to
445450
construct the source objects
446451
447452
"""
@@ -453,7 +458,7 @@ def __init__(self, model_data):
453458
get_cfg_schema_version(model_data)
454459
self._verify_schema_version()
455460
self._remove_metadata(model_data)
456-
self._parse_cfg(model_data)
461+
self._parse_cfg(model_data, components=components)
457462
self._check_user_input()
458463

459464
@staticmethod
@@ -465,7 +470,7 @@ def _remove_metadata(model_data):
465470
"""
466471
model_data.remove_section(DESCRIPTION_SECTION)
467472

468-
def _parse_cfg(self, cfg_data):
473+
def _parse_cfg(self, cfg_data, components=None):
469474
"""Parse a config_parser object into a externals description.
470475
"""
471476
def list_to_dict(input_list, convert_to_lower_case=True):
@@ -482,6 +487,8 @@ def list_to_dict(input_list, convert_to_lower_case=True):
482487

483488
for section in cfg_data.sections():
484489
name = config_string_cleaner(section.lower().strip())
490+
if components and name not in components:
491+
continue
485492
self[name] = {}
486493
self[name].update(list_to_dict(cfg_data.items(section)))
487494
self[name][self.REPO] = {}

manic/sourcetree.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
class _External(object):
2121
"""
22-
_External represents an external object in side a SourceTree
22+
_External represents an external object inside a SourceTree
2323
"""
2424

2525
# pylint: disable=R0902

test/test_sys_checkout.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,18 @@ def _check_container_full_pre_checkout(self, overall, tree):
752752
self._check_simple_opt_empty(tree)
753753
self._check_mixed_ext_branch_required_pre_checkout(overall, tree)
754754

755+
def _check_container_component_post_checkout(self, overall, tree):
756+
self.assertEqual(overall, 0)
757+
self._check_simple_opt_ok(tree)
758+
self._check_simple_tag_empty(tree)
759+
self._check_simple_branch_empty(tree)
760+
761+
def _check_container_component_post_checkout2(self, overall, tree):
762+
self.assertEqual(overall, 0)
763+
self._check_simple_opt_ok(tree)
764+
self._check_simple_tag_empty(tree)
765+
self._check_simple_branch_ok(tree)
766+
755767
def _check_container_full_post_checkout(self, overall, tree):
756768
self.assertEqual(overall, 0)
757769
self._check_simple_tag_ok(tree)
@@ -1219,6 +1231,38 @@ def test_container_full(self):
12191231
self.status_args)
12201232
self._check_container_full_post_checkout(overall, tree)
12211233

1234+
def test_container_component(self):
1235+
"""Verify that optional component checkout works
1236+
"""
1237+
# create the test repository
1238+
under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME)
1239+
1240+
# create the top level externals file
1241+
self._generator.container_full(under_test_dir)
1242+
1243+
# inital checkout, first try a nonexistant component argument noref
1244+
checkout_args = ['simp_opt', 'noref']
1245+
checkout_args.extend(self.checkout_args)
1246+
1247+
with self.assertRaises(RuntimeError):
1248+
self.execute_cmd_in_dir(under_test_dir, checkout_args)
1249+
1250+
checkout_args = ['simp_opt']
1251+
checkout_args.extend(self.checkout_args)
1252+
1253+
overall, tree = self.execute_cmd_in_dir(under_test_dir,
1254+
checkout_args)
1255+
1256+
overall, tree = self.execute_cmd_in_dir(under_test_dir,
1257+
self.status_args)
1258+
self._check_container_component_post_checkout(overall, tree)
1259+
checkout_args.append('simp_branch')
1260+
overall, tree = self.execute_cmd_in_dir(under_test_dir,
1261+
checkout_args)
1262+
overall, tree = self.execute_cmd_in_dir(under_test_dir,
1263+
self.status_args)
1264+
self._check_container_component_post_checkout2(overall, tree)
1265+
12221266
def test_mixed_simple(self):
12231267
"""Verify that a mixed use repo can serve as a 'full' container,
12241268
pulling in a set of externals and a seperate set of sub-externals.

0 commit comments

Comments
 (0)