Fix ignore-conflicts for extensions in views (#7167)

Fixes #7159

When activating extensions in external views, the --ignore-conflicts
option was being ignored. In this particular issue the conflict was
for the duplicate __init__ file for multiple python packages in the
same namespace, but in general any conflict for extensions would
cause an error whether or not --ignore-conflicts was set.

This also renames the 'force' option of do_activate to
'with_dependencies' and updates views to call do_activate with this
set to False (since it traverses the dependency dag anyway). This
isn't strictly required, it just avoids redundant calls.
This commit is contained in:
healther 2018-02-02 23:45:21 +01:00 committed by scheibelp
parent 0b6d7f7397
commit e3951c2a21
3 changed files with 28 additions and 9 deletions

View file

@ -61,4 +61,5 @@ def activate(parser, args):
if spec.package.is_activated(extensions_layout=layout): if spec.package.is_activated(extensions_layout=layout):
tty.die("Package %s is already activated." % specs[0].short_spec) tty.die("Package %s is already activated." % specs[0].short_spec)
spec.package.do_activate(extensions_layout=layout) spec.package.do_activate(extensions_layout=layout,
with_dependencies=not args.force)

View file

@ -94,7 +94,7 @@ def add_specs(self, *specs, **kwargs):
def add_extension(self, spec): def add_extension(self, spec):
""" """
Add (link) an extension in this view. Add (link) an extension in this view. Does not add dependencies.
""" """
raise NotImplementedError raise NotImplementedError
@ -228,6 +228,9 @@ def add_extension(self, spec):
try: try:
if not spec.package.is_activated(self.extensions_layout): if not spec.package.is_activated(self.extensions_layout):
spec.package.do_activate( spec.package.do_activate(
ignore_conflicts=self.ignore_conflicts,
with_dependencies=False, # already taken care of
# in add_specs()
verbose=self.verbose, verbose=self.verbose,
extensions_layout=self.extensions_layout) extensions_layout=self.extensions_layout)

View file

@ -1825,12 +1825,17 @@ def _sanity_check_extension(self):
raise ActivationError("%s does not extend %s!" % raise ActivationError("%s does not extend %s!" %
(self.name, self.extendee.name)) (self.name, self.extendee.name))
def do_activate(self, force=False, verbose=True, extensions_layout=None): def do_activate(self, with_dependencies=True, ignore_conflicts=False,
verbose=True, extensions_layout=None):
"""Called on an extension to invoke the extendee's activate method. """Called on an extension to invoke the extendee's activate method.
Commands should call this routine, and should not call Commands should call this routine, and should not call
activate() directly. activate() directly.
""" """
if verbose:
tty.msg("Activating extension %s for %s" %
(self.spec.cshort_spec, self.extendee_spec.cshort_spec))
self._sanity_check_extension() self._sanity_check_extension()
if extensions_layout is None: if extensions_layout is None:
@ -1840,16 +1845,19 @@ def do_activate(self, force=False, verbose=True, extensions_layout=None):
self.extendee_spec, self.spec) self.extendee_spec, self.spec)
# Activate any package dependencies that are also extensions. # Activate any package dependencies that are also extensions.
if not force: if with_dependencies:
for spec in self.dependency_activations(): for spec in self.dependency_activations():
if not spec.package.is_activated( if not spec.package.is_activated(
extensions_layout=extensions_layout): extensions_layout=extensions_layout):
spec.package.do_activate( spec.package.do_activate(
force=force, verbose=verbose, with_dependencies=with_dependencies,
ignore_conflicts=ignore_conflicts,
verbose=verbose,
extensions_layout=extensions_layout) extensions_layout=extensions_layout)
self.extendee_spec.package.activate( self.extendee_spec.package.activate(
self, extensions_layout=extensions_layout, **self.extendee_args) self, extensions_layout=extensions_layout,
ignore_conflicts=ignore_conflicts, **self.extendee_args)
extensions_layout.add_extension(self.extendee_spec, self.spec) extensions_layout.add_extension(self.extendee_spec, self.spec)
@ -1863,7 +1871,7 @@ def dependency_activations(self):
return (spec for spec in self.spec.traverse(root=False, deptype='run') return (spec for spec in self.spec.traverse(root=False, deptype='run')
if spec.package.extends(self.extendee_spec)) if spec.package.extends(self.extendee_spec))
def activate(self, extension, **kwargs): def activate(self, extension, ignore_conflicts=False, **kwargs):
"""Make extension package usable by linking all its files to a target """Make extension package usable by linking all its files to a target
provided by the directory layout (depending if the user wants to provided by the directory layout (depending if the user wants to
activate globally or in a specified file system view). activate globally or in a specified file system view).
@ -1883,11 +1891,18 @@ def ignore(filename):
kwargs.get('ignore', lambda f: False)(filename)) kwargs.get('ignore', lambda f: False)(filename))
tree = LinkTree(extension.prefix) tree = LinkTree(extension.prefix)
conflict = tree.find_conflict(target, ignore=ignore) conflict = tree.find_conflict(target, ignore=ignore)
if conflict: if not conflict:
pass
elif ignore_conflicts:
tty.warn("While activating %s, found conflict %s" %
(self.spec.cshort_spec, conflict))
else:
raise ExtensionConflictError(conflict) raise ExtensionConflictError(conflict)
tree.merge(target, ignore=ignore, link=extensions_layout.link) tree.merge(target, ignore=ignore, link=extensions_layout.link,
ignore_conflicts=ignore_conflicts)
def do_deactivate(self, **kwargs): def do_deactivate(self, **kwargs):
"""Called on the extension to invoke extendee's deactivate() method. """Called on the extension to invoke extendee's deactivate() method.