def cross_reference_products(<EOL>eups_products,<EOL>manifest_products,<EOL>ignore_manifest_versions=False,<EOL>fail_fast=False,<EOL>):
products = {}<EOL>problems = []<EOL>for name, eups_data in eups_products.items():<EOL><INDENT>try:<EOL><INDENT>manifest_data = manifest_products[name]<EOL><DEDENT>except KeyError:<EOL><INDENT>yikes = RuntimeError(textwrap.dedent("""<STR_LIT>""").format(<EOL>product=name,<EOL>eups_version=eups_data['<STR_LIT>'],<EOL>))<EOL>if fail_fast:<EOL><INDENT>raise yikes from None<EOL><DEDENT>problems.append(yikes)<EOL>error(yikes)<EOL><DEDENT>if ignore_manifest_versions:<EOL><INDENT>manifest_data = manifest_data.copy()<EOL>manifest_data['<STR_LIT>'] = eups_data['<STR_LIT>']<EOL><DEDENT>if eups_data['<STR_LIT>'] != manifest_data['<STR_LIT>']:<EOL><INDENT>yikes = RuntimeError(textwrap.dedent("""<STR_LIT>""").format(<EOL>product=name,<EOL>eups_eups_version=eups_data['<STR_LIT>'],<EOL>manifest_eups_version=manifest_data['<STR_LIT>'],<EOL>))<EOL>if fail_fast:<EOL><INDENT>raise yikes<EOL><DEDENT>problems.append(yikes)<EOL>error(yikes)<EOL><DEDENT>products[name] = eups_data.copy()<EOL>products[name].update(manifest_data)<EOL><DEDENT>if problems:<EOL><INDENT>error("<STR_LIT>".format(n=len(problems)))<EOL><DEDENT>return products, problems<EOL>
Cross reference EupsTag and Manifest data and return a merged result

Parameters
----------
eups_products:
manifest:
fail_fast: bool
ignore_manifest_versions: bool

Returns
-------
products: dict

Raises
------
RuntimeError
    Upon error if `fail_fast` is `True`.