diff --git a/src/deploy_tools/deploy.py b/src/deploy_tools/deploy.py index 4e6ff76..00f03c9 100644 --- a/src/deploy_tools/deploy.py +++ b/src/deploy_tools/deploy.py @@ -6,12 +6,13 @@ from .models.changes import DeploymentChanges from .models.module import Release from .modulefile import ( - DEFAULT_VERSION_FILENAME, apply_default_versions, - deprecate_modulefile, - restore_modulefile, + deprecate_modulefile_link, + restore_modulefile_link, ) +MODULE_VERSIONS_GLOB = f"[!{Layout.DEFAULT_VERSION_FILENAME}]*" + def deploy_changes(changes: DeploymentChanges, layout: Layout) -> None: """Perform the Deploy step for the specified changes.""" @@ -46,20 +47,19 @@ def _remove_releases(to_remove: list[Release], layout: Layout) -> None: def _deploy_new_releases(to_add: list[Release], layout: Layout) -> None: """Deploy modules from the provided list.""" _deploy_releases(to_add, layout) - build_layout = layout.build_layout for release in to_add: name = release.module.name version = release.module.version deprecated = release.deprecated - built_modulefile = build_layout.get_built_modulefile(name, version) - modulefile_link = layout.get_modulefile( + modulefile = layout.get_modulefile(name, version) + modulefile_link = layout.get_modulefile_link( name, version, from_deprecated=deprecated ) modulefile_link.parent.mkdir(parents=True, exist_ok=True) - os.symlink(built_modulefile, modulefile_link) + os.symlink(modulefile, modulefile_link) def _deploy_releases( @@ -84,18 +84,18 @@ def _deploy_releases( def _deprecate_releases(to_deprecate: list[Release], layout: Layout) -> None: """Deprecate a list of modules. - This will move the modulefile to a 'deprecated' directory. If the modulefile path is - set up to include the 'deprecated' directory, all modulefiles should continue to - work. + For each module, this will move the modulefile link to a 'deprecated' directory. If + the user's MODULEPATH is set up to include the 'deprecated' directory, all + modules should be available as before. """ for release in to_deprecate: - deprecate_modulefile(release.module.name, release.module.version, layout) + deprecate_modulefile_link(release.module.name, release.module.version, layout) def _remove_deployed_module( name: str, version: str, layout: Layout, from_deprecated: bool = False ) -> None: - modulefile = layout.get_modulefile(name, version, from_deprecated) + modulefile = layout.get_modulefile_link(name, version, from_deprecated) modulefile.unlink() _remove_module(name, version, layout) @@ -110,7 +110,7 @@ def _remove_module(name: str, version: str, layout: Layout) -> None: def _restore_releases(to_restore: list[Release], layout: Layout) -> None: """Restore a previously deprecated module.""" for release in to_restore: - restore_modulefile(release.module.name, release.module.version, layout) + restore_modulefile_link(release.module.name, release.module.version, layout) def _remove_name_folders( @@ -119,25 +119,34 @@ def _remove_name_folders( removed: list[Release], layout: Layout, ) -> None: - """Remove module name folders where all versions have been removed.""" + """Remove module name folders where all versions have been removed. + + Several types of path are of the form /name/version. When removing version + files in operations such as deprecation, if all versions are removed the parent + folder (called name folder here) will still exist. This function is designed to + remove them. + + Note that the non-deprecated modulefile name folder will not be empty, as the + default version file will still exist. + """ for release in deprecated: - _delete_modulefile_name_folder(layout, release.module.name) + _delete_modulefiles_name_folder(layout, release.module.name) for release in restored: - _delete_modulefile_name_folder(layout, release.module.name, True) + _delete_modulefiles_name_folder(layout, release.module.name, True) for release in removed: - _delete_modulefile_name_folder(layout, release.module.name, True) + _delete_modulefiles_name_folder(layout, release.module.name, True) _delete_name_folder(release.module.name, layout.modules_root) -def _delete_modulefile_name_folder( +def _delete_modulefiles_name_folder( layout: Layout, name: str, from_deprecated: bool = False ) -> None: modulefiles_name_path = layout.get_modulefiles_root(from_deprecated) / name - module_versions_glob = f"[!{DEFAULT_VERSION_FILENAME}]*" - if next(modulefiles_name_path.glob(module_versions_glob), None) is None: + # Ignore the default version file when checking for existing modulefile links + if next(modulefiles_name_path.glob(MODULE_VERSIONS_GLOB), None) is None: shutil.rmtree(modulefiles_name_path) diff --git a/src/deploy_tools/layout.py b/src/deploy_tools/layout.py index c7a7eb2..c5b171f 100644 --- a/src/deploy_tools/layout.py +++ b/src/deploy_tools/layout.py @@ -49,6 +49,7 @@ class Layout: MODULEFILES_ROOT_NAME = "modulefiles" DEPRECATED_ROOT_NAME = "deprecated" DEFAULT_BUILD_ROOT_NAME = "build" + DEFAULT_VERSION_FILENAME = ".version" DEPLOYMENT_SNAPSHOT_FILENAME = "deployment.yaml" @@ -75,11 +76,20 @@ def get_modulefiles_root(self, from_deprecated: bool = False) -> Path: else self.modulefiles_root ) - def get_modulefile( + def get_modulefile_link( self, name: str, version: str, from_deprecated: bool = False ) -> Path: return self.get_modulefiles_root(from_deprecated) / name / version + def get_modulefile(self, name: str, version: str) -> Path: + return ( + self.get_module_folder(name, version) + / ModuleBuildLayout.BUILT_MODULEFILE_FILENAME + ) + + def get_default_version_file(self, name: str) -> Path: + return self.modulefiles_root / name / self.DEFAULT_VERSION_FILENAME + @property def deployment_root(self) -> Path: return self._root diff --git a/src/deploy_tools/modulefile.py b/src/deploy_tools/modulefile.py index 03f9b39..8343083 100644 --- a/src/deploy_tools/modulefile.py +++ b/src/deploy_tools/modulefile.py @@ -8,13 +8,12 @@ type ModuleVersionsByName = dict[str, list[str]] -DEFAULT_VERSION_FILENAME = ".version" -VERSION_GLOB = f"*/[!{DEFAULT_VERSION_FILENAME}]*" +VERSION_GLOB = f"*/[!{Layout.DEFAULT_VERSION_FILENAME}]*" DEFAULT_VERSION_REGEX = "^set ModulesVersion (.*)$" -def deprecate_modulefile(name: str, version: str, layout: Layout) -> None: +def deprecate_modulefile_link(name: str, version: str, layout: Layout) -> None: _move_modulefile_link( name, version, @@ -23,7 +22,7 @@ def deprecate_modulefile(name: str, version: str, layout: Layout) -> None: ) -def restore_modulefile(name: str, version: str, layout: Layout) -> None: +def restore_modulefile_link(name: str, version: str, layout: Layout) -> None: _move_modulefile_link( name, version, @@ -58,13 +57,15 @@ def get_deployed_modulefile_versions( def is_modulefile_deployed( name: str, version: str, layout: Layout, in_deprecated: bool = False ) -> bool: - modulefile = layout.get_modulefile(name, version, from_deprecated=in_deprecated) - return modulefile.exists() + modulefile_link = layout.get_modulefile_link( + name, version, from_deprecated=in_deprecated + ) + return modulefile_link.exists() def get_default_modulefile_version(name: str, layout: Layout) -> str | None: version_regex = re.compile(DEFAULT_VERSION_REGEX) - default_version_file = layout.modulefiles_root / name / DEFAULT_VERSION_FILENAME + default_version_file = layout.get_default_version_file(name) with open(default_version_file) as f: for line in f.readlines(): @@ -81,16 +82,16 @@ def apply_default_versions( deployed_module_versions = get_deployed_modulefile_versions(layout) for name in deployed_module_versions: - version_file = layout.modulefiles_root / name / DEFAULT_VERSION_FILENAME + default_version_file = layout.get_default_version_file(name) if name in default_versions: params = {"version": default_versions[name]} templater.create( - version_file, + default_version_file, TemplateType.MODULEFILE_VERSION, params, overwrite=True, ) else: - version_file.unlink(missing_ok=True) + default_version_file.unlink(missing_ok=True) diff --git a/src/deploy_tools/display.py b/src/deploy_tools/print_updates.py similarity index 100% rename from src/deploy_tools/display.py rename to src/deploy_tools/print_updates.py diff --git a/src/deploy_tools/validate.py b/src/deploy_tools/validate.py index 5a8eefd..e0a33ad 100644 --- a/src/deploy_tools/validate.py +++ b/src/deploy_tools/validate.py @@ -5,7 +5,6 @@ from .build import build from .check_deploy import check_deploy_can_run -from .display import print_updates from .layout import Layout from .models.changes import DeploymentChanges, ReleaseChanges from .models.deployment import ( @@ -18,6 +17,7 @@ from .modulefile import ( ModuleVersionsByName, ) +from .print_updates import print_updates from .snapshot import load_snapshot