diff --git a/.github/scripts/tests/test_utils.py b/.github/scripts/tests/test_utils.py index 0265ec3e7..b507ae7d5 100644 --- a/.github/scripts/tests/test_utils.py +++ b/.github/scripts/tests/test_utils.py @@ -1,9 +1,18 @@ import os.path import utils +from themes import Theme def test_get_root_of_vault() -> None: root = utils.get_root_of_vault() contributing = os.path.join(root, 'CONTRIBUTING.md') assert os.path.exists(contributing), contributing + + +def test_get_output_path() -> None: + assert utils.get_output_path(Theme.template, 'CONTRIBUTING') == '../../02 - Community Expansions/02.05 All Community Expansions/Themes/CONTRIBUTING.md' + + +def test_get_output_dir() -> None: + assert utils.get_output_dir(Theme.template) == '../../02 - Community Expansions/02.05 All Community Expansions/Themes' diff --git a/.github/scripts/themes.py b/.github/scripts/themes.py index 3aec97d44..b867b684e 100644 --- a/.github/scripts/themes.py +++ b/.github/scripts/themes.py @@ -11,7 +11,7 @@ from core_plugins import CORE_PLUGINS from utils import ( THEME_CSS_FILE, - get_output_dir, + get_output_path, get_theme_css, FileGroups, add_file_group, get_template, get_json_from_github @@ -245,7 +245,7 @@ def get_theme_previous_download_count_or_none(template: Template, current_name: Read the theme file from disk, and return the previously-saved download count :return: The saved theme download count, or None if this could not be obtained """ - file_name = get_output_dir(template, current_name) + file_name = get_output_path(template, current_name) if not os.path.exists(file_name): # This is a new theme, so we don't yet have a previous download count: return None @@ -261,7 +261,7 @@ def get_theme_previous_download_count_or_none(template: Template, current_name: @staticmethod def set_theme_download_count(template: Template, current_name: str, new_download_count: int, verbose: bool) -> None: - file_name = get_output_dir(template, current_name) + file_name = get_output_path(template, current_name) if not os.path.exists(file_name): if verbose: diff --git a/.github/scripts/update_releases.py b/.github/scripts/update_releases.py index 5692b7ea5..6e9c4beae 100755 --- a/.github/scripts/update_releases.py +++ b/.github/scripts/update_releases.py @@ -18,7 +18,9 @@ print_progress_bar, write_template_file, add_file_group, + get_output_path, get_output_dir, + FileNameCaseCollisionsPreventer, ) from themes import ThemeList, Theme, ThemeDownloadCount, get_community_themes @@ -26,6 +28,8 @@ def process_released_plugins(overwrite: bool = False, verbose: bool = False) -> PluginList: print("-----\nProcessing plugins....\n") template = get_template("plugin") + plugins_dir = get_output_dir(template) + collision_preventer = FileNameCaseCollisionsPreventer(plugins_dir) plugin_list: PluginList = get_community_plugins() valid_plugins: PluginList = list() @@ -41,7 +45,7 @@ def process_released_plugins(overwrite: bool = False, verbose: bool = False) -> continue group = write_template_file( - template, plugin.id(), overwrite=overwrite, verbose=verbose, **plugin.data() + template, collision_preventer.get_name(plugin.id()), overwrite=overwrite, verbose=verbose, **plugin.data() ) valid_plugins.append(plugin) @@ -67,11 +71,18 @@ def process_released_themes(overwrite: bool = False, verbose: bool = False) -> T theme_downloads = ThemeDownloadCount.get_theme_downloads() + themes_dir = get_output_dir(Theme.template) + collision_preventer = FileNameCaseCollisionsPreventer(themes_dir) + for index, theme in enumerate(theme_list): current_name, valid = theme.collect_data_for_theme(theme_downloads, file_groups) if not valid: continue + # Prefer the existing capitalisation of any existing filename, + # to prevent case-conflicts. + current_name = collision_preventer.get_name(current_name) + group = write_template_file( Theme.template, current_name, overwrite=overwrite, verbose=verbose, **theme.data() ) @@ -123,7 +134,7 @@ def update_uncategorized_plugins(valid_plugins: PluginList, overwrite: bool = Tr ) # Alphabetize the plugin list - file_path = get_output_dir(template, UNCATEGORIZED) + file_path = get_output_path(template, UNCATEGORIZED) absolute_file_path = os.path.abspath(file_path) sort_links_under_heading(absolute_file_path) @@ -134,13 +145,15 @@ def process_authors(themes: ThemeList, verbose: bool = False) -> None: print("-----\nProcessing authors....\n") template = get_template("author") + authors_dir = get_output_dir(template) + collision_preventer = FileNameCaseCollisionsPreventer(authors_dir) all_authors = collate_authors(themes, plugins) print("\nCreating author notes....\n") file_groups: FileGroups = dict() for user, author_info in all_authors.items(): group = write_template_file( - template, user, overwrite=overwrite, verbose=verbose, **author_info + template, collision_preventer.get_name(user), overwrite=overwrite, verbose=verbose, **author_info ) add_file_group(file_groups, group, user) diff --git a/.github/scripts/utils.py b/.github/scripts/utils.py index c694bfce6..9847a8807 100755 --- a/.github/scripts/utils.py +++ b/.github/scripts/utils.py @@ -2,6 +2,7 @@ import json import glob import typing +from pathlib import Path from re import sub, search from typing import Dict, List, Union, Any @@ -63,12 +64,18 @@ def get_template_from_directory(directory: str, template_name_with_extensions: s return env.get_template(template_name_with_extensions) -def get_output_dir(template: Template, file_name: str) -> str: +def get_output_path(template: Template, file_name: str) -> str: + return os.path.join( + get_output_dir(template), + "{}.md".format(file_name), + ) + + +def get_output_dir(template: Template) -> str: template_name, _, _ = template.name.split(".") return os.path.join( "../..", OUTPUT_DIR.get(template_name, "08 - Seedbox"), - "{}.md".format(file_name), ) @@ -77,7 +84,7 @@ def write_template_file(template: Template, overwrite: bool = False, verbose: bool = False, **kwargs: Any) -> str: - file_path = get_output_dir(template, file_name) + file_path = get_output_path(template, file_name) absolute_file_path = os.path.abspath(file_path) file_content = render_template_for_file(template, absolute_file_path, **kwargs) @@ -296,3 +303,24 @@ def write_file(absolute_path: str, replacement: str) -> None: f.write(replacement) +class FileNameCaseCollisionsPreventer: + def __init__(self, directory: str) -> None: + self.file_case_lookup = dict() + for filename in os.listdir(directory): + base_name = Path(filename).stem + self.file_case_lookup[base_name.lower()] = base_name + + def get_name(self, current_name: str) -> str: + """ + Prefer the existing capitalisation of any existing filename, + to prevent case-conflicts. + + :param current_name: + :return: + """ + if current_name.lower() in self.file_case_lookup: + existing_case = self.file_case_lookup[current_name.lower()] + if existing_case != current_name: + print(f'Overriding filename {current_name} to {existing_case}') + current_name = existing_case + return current_name