diff --git a/extensions/templates/extensions/submit.html b/extensions/templates/extensions/submit.html index d77153f0..e896a7bd 100644 --- a/extensions/templates/extensions/submit.html +++ b/extensions/templates/extensions/submit.html @@ -59,6 +59,13 @@ {% include "common/components/field.html" with field=form.source label='File' classes="js-agree-with-terms-trigger js-submit-form-file-input" %} + + {% if form.errors %} +
+ Build your extension using the command-line tool to catch and prevent most of these errors. +
+ {% endif %} +
{% include "common/components/field.html" with field=form.agreed_with_terms classes="js-agree-with-terms-trigger js-agree-with-terms-checkbox" %} diff --git a/extensions/tests/files/invalid-theme-multiple-xmls-macosx.zip b/extensions/tests/files/invalid-theme-multiple-xmls-macosx.zip new file mode 100644 index 00000000..2e8ccee1 Binary files /dev/null and b/extensions/tests/files/invalid-theme-multiple-xmls-macosx.zip differ diff --git a/extensions/tests/test_submit.py b/extensions/tests/test_submit.py index dd4d16b3..687726bd 100644 --- a/extensions/tests/test_submit.py +++ b/extensions/tests/test_submit.py @@ -109,19 +109,20 @@ EXPECTED_VALIDATION_ERRORS = { ], }, 'invalid-addon-no-init.zip': { - 'source': ['An add-on should have an __init__.py file.'], + 'source': ['Add-on file missing: __init__.py.'], }, 'invalid-addon-dir-no-init.zip': { - 'source': ['An add-on should have an __init__.py file.'], + 'source': ['Add-on file missing: __init__.py.'], }, 'invalid-no-manifest.zip': { 'source': ['The manifest file is missing.'], }, - 'invalid-manifest-toml.zip': {'source': ['Could not parse the manifest file.']}, - 'invalid-theme-multiple-xmls.zip': {'source': ['A theme should have exactly one XML file.']}, + 'invalid-manifest-toml.zip': {'source': ['Manifest file contains invalid code.']}, + 'invalid-theme-multiple-xmls.zip': {'source': ['Themes can only contain one XML file.']}, + 'invalid-theme-multiple-xmls-macosx.zip': {'source': ['Archive contains forbidden files or directories: __MACOSX/']}, 'invalid-missing-wheels.zip': { 'source': [ - 'A declared wheel is missing in the zip file, expected path: addon/wheels/test-wheel-whatever.whl' + 'Python wheel missing: addon/wheels/test-wheel-whatever.whl' ] }, } diff --git a/files/forms.py b/files/forms.py index 355b0944..f8e2e254 100644 --- a/files/forms.py +++ b/files/forms.py @@ -34,13 +34,13 @@ class FileForm(forms.ModelForm): 'The manifest file should be at the top level of the archive, or one level deep.' ), # TODO: surface TOML parsing errors? - 'invalid_manifest_toml': _('Could not parse the manifest file.'), - 'invalid_missing_init': _('An add-on should have an __init__.py file.'), - 'missing_or_multiple_theme_xml': _('A theme should have exactly one XML file.'), + 'invalid_manifest_toml': _('Manifest file contains invalid code.'), + 'invalid_missing_init': mark_safe(_('Add-on file missing: __init__.py.')), + 'missing_or_multiple_theme_xml': mark_safe(_('Themes can only contain one XML file.')), 'invalid_zip_archive': msg_only_zip_files, 'missing_manifest_toml': _('The manifest file is missing.'), - 'missing_wheel': _('A declared wheel is missing in the zip file, expected path: %(path)s'), - 'forbidden_filepaths': _('Archive contains forbidden files or directories: %(paths)s'), + 'missing_wheel': _('Python wheel missing: %(path)s'), # TODO %(path)s + 'forbidden_filepaths': _('Archive contains forbidden files or directories: %(paths)s'), #TODO %(paths)s } class Meta: diff --git a/files/utils.py b/files/utils.py index 4a03d911..1224b865 100644 --- a/files/utils.py +++ b/files/utils.py @@ -172,10 +172,21 @@ def find_forbidden_filepaths(file_list): def validate_file_list(toml_content, manifest_filepath, file_list): """Check the files in in the archive against manifest.""" error_codes = [] + + found_forbidden_filepaths = find_forbidden_filepaths(file_list) + if found_forbidden_filepaths: + error_codes.append( + { + 'code': 'forbidden_filepaths', + 'params': {'paths': ', '.join(found_forbidden_filepaths)}, + } + ) type_slug = toml_content['type'] if type_slug == 'theme': theme_xmls = filter_paths_by_ext(file_list, '.xml') - if len(list(theme_xmls)) != 1: + # Special treatment for Mac, so the same problem (__MACOSX folders) + # doesn't lead to two errors showing. + if len(list(theme_xmls)) != 1 and '__MACOSX/' not in found_forbidden_filepaths: error_codes.append('missing_or_multiple_theme_xml') elif type_slug == 'add-on': # __init__.py is expected to be next to the manifest @@ -192,14 +203,6 @@ def validate_file_list(toml_content, manifest_filepath, file_list): error_codes.append( {'code': 'missing_wheel', 'params': {'path': expected_wheel_path}} ) - found_forbidden_filepaths = find_forbidden_filepaths(file_list) - if found_forbidden_filepaths: - error_codes.append( - { - 'code': 'forbidden_filepaths', - 'params': {'paths': ', '.join(found_forbidden_filepaths)}, - } - ) return error_codes