From 0d3c17653e1f3f40313e5535823edd8a701240ad Mon Sep 17 00:00:00 2001 From: Mohammad Alisafaee Date: Fri, 29 Apr 2022 15:02:46 +0430 Subject: [PATCH] feat(cli): gc command (#2866) --- docs/_static/cheatsheet/cheatsheet.pdf | Bin 419988 -> 420071 bytes docs/cheatsheet_hash | 2 +- docs/reference/commands.rst | 7 +++ .../command_builder/client_dispatcher.py | 6 +-- renku/command/gc.py | 27 ++++++++++ renku/command/init.py | 2 +- renku/core/constant.py | 26 +++++++++ renku/core/dataset/constant.py | 5 +- renku/core/dataset/dataset_add.py | 3 +- renku/core/errors.py | 2 +- renku/core/interface/client_dispatcher.py | 7 ++- renku/core/management/__init__.py | 3 -- renku/core/management/config.py | 2 +- renku/core/management/migrate.py | 4 +- renku/core/management/repository.py | 2 +- renku/core/migration/m_0003__2_initial.py | 2 +- renku/core/misc/__init__.py | 18 +++++++ renku/core/misc/gc.py | 38 +++++++++++++ renku/core/template/template.py | 1 + renku/core/util/contexts.py | 2 +- renku/core/util/git.py | 2 +- renku/core/util/metadata.py | 2 +- renku/core/workflow/plan_factory.py | 4 +- renku/core/workflow/providers/toil.py | 3 +- renku/domain_model/template.py | 2 +- renku/infrastructure/repository.py | 7 ++- renku/ui/cli/__init__.py | 4 +- renku/ui/cli/gc.py | 35 ++++++++++++ renku/ui/service/controllers/api/mixins.py | 2 +- tests/cli/test_datasets.py | 2 +- tests/cli/test_errors.py | 1 + tests/cli/test_gc.py | 51 ++++++++++++++++++ tests/cli/test_gitignore.py | 1 + tests/cli/test_migrate.py | 3 +- 34 files changed, 239 insertions(+), 39 deletions(-) create mode 100644 renku/command/gc.py create mode 100644 renku/core/constant.py create mode 100644 renku/core/misc/__init__.py create mode 100644 renku/core/misc/gc.py create mode 100644 renku/ui/cli/gc.py create mode 100644 tests/cli/test_gc.py diff --git a/docs/_static/cheatsheet/cheatsheet.pdf b/docs/_static/cheatsheet/cheatsheet.pdf index c2c44a1026999806d51d9cd922269e9a4ecc5f42..153df99dddbc4fbd1f24a3ac6e98c63d825ad504 100644 GIT binary patch delta 6559 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 Nd>Bkj@)`;l{{xmynJ54N diff --git a/docs/cheatsheet_hash b/docs/cheatsheet_hash index 8a56511f36..23e649a542 100644 --- a/docs/cheatsheet_hash +++ b/docs/cheatsheet_hash @@ -1,2 +1,2 @@ -8f835f7c5c76b60f8cd9785fd1e0cf31 cheatsheet.tex +3e7d7567c17eba64945b70a3c1009343 cheatsheet.tex c70c179e07f04186ec05497564165f11 sdsc_cheatsheet.cls diff --git a/docs/reference/commands.rst b/docs/reference/commands.rst index a2b3f1a009..198aa433a9 100644 --- a/docs/reference/commands.rst +++ b/docs/reference/commands.rst @@ -62,6 +62,13 @@ Renku Command Line .. automodule:: renku.ui.cli.dataset +.. _cli-gc: + +``renku gc`` +------------ + +.. automodule:: renku.ui.cli.gc + .. _cli-graph: ``renku graph`` diff --git a/renku/command/command_builder/client_dispatcher.py b/renku/command/command_builder/client_dispatcher.py index 6628d23d87..030baf62e1 100644 --- a/renku/command/command_builder/client_dispatcher.py +++ b/renku/command/command_builder/client_dispatcher.py @@ -17,11 +17,11 @@ # limitations under the License. """Renku client dispatcher.""" from pathlib import Path -from typing import Optional, Union +from typing import Union from renku.core import errors +from renku.core.constant import RENKU_HOME from renku.core.interface.client_dispatcher import IClientDispatcher -from renku.core.management import RENKU_HOME from renku.core.management.client import LocalClient @@ -35,7 +35,7 @@ def __init__(self): self.client_stack = [] @property - def current_client(self) -> Optional[LocalClient]: + def current_client(self) -> LocalClient: """Get the currently active client.""" if len(self.client_stack) == 0: raise errors.ConfigurationError("No client configured for injection") diff --git a/renku/command/gc.py b/renku/command/gc.py new file mode 100644 index 0000000000..dae827a2eb --- /dev/null +++ b/renku/command/gc.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2020 - Swiss Data Science Center (SDSC) +# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and +# Eidgenössische Technische Hochschule Zürich (ETHZ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Garbage collection and cleanup command.""" + +from renku.command.command_builder.command import Command + + +def gc_command(): + """Command to clean up project's caches.""" + from renku.core.misc.gc import remove_caches + + return Command().command(remove_caches).lock_project() diff --git a/renku/command/init.py b/renku/command/init.py index a2012d239f..6d354ddce1 100644 --- a/renku/command/init.py +++ b/renku/command/init.py @@ -26,10 +26,10 @@ from renku.command.command_builder.command import Command, inject from renku.command.git import set_git_home from renku.core import errors +from renku.core.constant import RENKU_HOME from renku.core.interface.client_dispatcher import IClientDispatcher from renku.core.interface.database_dispatcher import IDatabaseDispatcher from renku.core.interface.database_gateway import IDatabaseGateway -from renku.core.management import RENKU_HOME from renku.core.migration.utils import OLD_METADATA_PATH from renku.core.template.template import ( FileAction, diff --git a/renku/core/constant.py b/renku/core/constant.py new file mode 100644 index 0000000000..c47e79ffcc --- /dev/null +++ b/renku/core/constant.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2017-2022 - Swiss Data Science Center (SDSC) +# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and +# Eidgenössische Technische Hochschule Zürich (ETHZ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Renku core constants.""" + +CACHE = "cache" +"""Directory to cache transient data.""" + +RENKU_HOME = ".renku" +"""Project directory name.""" + +RENKU_TMP = "tmp" diff --git a/renku/core/dataset/constant.py b/renku/core/dataset/constant.py index c520a01efb..0ea71a549e 100644 --- a/renku/core/dataset/constant.py +++ b/renku/core/dataset/constant.py @@ -19,16 +19,13 @@ from pathlib import Path -from renku.core.management import RENKU_HOME +from renku.core.constant import RENKU_HOME from renku.core.management.repository import RepositoryApiMixin from renku.domain_model.refs import LinkReference POINTERS = "pointers" """Directory for storing external pointer files.""" -CACHE = "cache" -"""Directory to cache transient data.""" - DATASET_IMAGES = "dataset_images" """Directory for dataset images.""" diff --git a/renku/core/dataset/dataset_add.py b/renku/core/dataset/dataset_add.py index aec675bd5e..d252bcc494 100644 --- a/renku/core/dataset/dataset_add.py +++ b/renku/core/dataset/dataset_add.py @@ -30,7 +30,8 @@ from renku.command.command_builder.command import inject from renku.core import errors -from renku.core.dataset.constant import CACHE, renku_pointers_path +from renku.core.constant import CACHE +from renku.core.dataset.constant import renku_pointers_path from renku.core.dataset.context import DatasetContext from renku.core.dataset.datasets_provenance import DatasetsProvenance from renku.core.dataset.pointer_file import create_external_file diff --git a/renku/core/errors.py b/renku/core/errors.py index 27d94a1ea3..e0cf4796ec 100644 --- a/renku/core/errors.py +++ b/renku/core/errors.py @@ -23,7 +23,7 @@ import click -from renku.core.management import RENKU_HOME +from renku.core.constant import RENKU_HOME class RenkuException(Exception): diff --git a/renku/core/interface/client_dispatcher.py b/renku/core/interface/client_dispatcher.py index 99b3ec87b2..1ca6ddcfbc 100644 --- a/renku/core/interface/client_dispatcher.py +++ b/renku/core/interface/client_dispatcher.py @@ -19,7 +19,10 @@ from abc import ABC from pathlib import Path -from typing import Union +from typing import TYPE_CHECKING, Union + +if TYPE_CHECKING: + from renku.core.management.client import LocalClient class IClientDispatcher(ABC): @@ -29,7 +32,7 @@ class IClientDispatcher(ABC): """ @property - def current_client(self): + def current_client(self) -> "LocalClient": """Get the currently active client.""" raise NotImplementedError diff --git a/renku/core/management/__init__.py b/renku/core/management/__init__.py index ca002aac92..08fb1a7a08 100644 --- a/renku/core/management/__init__.py +++ b/renku/core/management/__init__.py @@ -16,6 +16,3 @@ # See the License for the specific language governing permissions and # limitations under the License. """Renku repository management.""" - -RENKU_HOME = ".renku" -"""Project directory name.""" diff --git a/renku/core/management/config.py b/renku/core/management/config.py index 13403db80b..32f33b1117 100644 --- a/renku/core/management/config.py +++ b/renku/core/management/config.py @@ -25,7 +25,7 @@ import click import portalocker -from renku.core.management import RENKU_HOME +from renku.core.constant import RENKU_HOME from renku.domain_model.enums import ConfigFilter APP_NAME = "Renku" diff --git a/renku/core/management/migrate.py b/renku/core/management/migrate.py index d2e0a4c968..4196391732 100644 --- a/renku/core/management/migrate.py +++ b/renku/core/management/migrate.py @@ -37,6 +37,7 @@ from packaging.version import Version from renku.command.command_builder.command import inject +from renku.core.constant import RENKU_TMP from renku.core.errors import ( DockerfileUpdateError, MigrationError, @@ -55,7 +56,6 @@ read_project_version, ) from renku.core.util import communication -from renku.core.workflow.plan_factory import RENKU_TMP try: import importlib_resources @@ -165,7 +165,7 @@ def migrate( def _remove_untracked_renku_files(renku_path): - from renku.core.dataset.constant import CACHE + from renku.core.constant import CACHE untracked_paths = [RENKU_TMP, CACHE, "vendors"] for path in untracked_paths: diff --git a/renku/core/management/repository.py b/renku/core/management/repository.py index 9533f51316..4647880922 100644 --- a/renku/core/management/repository.py +++ b/renku/core/management/repository.py @@ -30,9 +30,9 @@ from renku.command.command_builder import inject from renku.core import errors from renku.core.compat import Path +from renku.core.constant import RENKU_HOME from renku.core.interface.database_gateway import IDatabaseGateway from renku.core.interface.project_gateway import IProjectGateway -from renku.core.management import RENKU_HOME from renku.core.management.git import GitCore from renku.core.util.git import default_path from renku.domain_model.enums import ConfigFilter diff --git a/renku/core/migration/m_0003__2_initial.py b/renku/core/migration/m_0003__2_initial.py index 5c2287266d..ec146c3028 100644 --- a/renku/core/migration/m_0003__2_initial.py +++ b/renku/core/migration/m_0003__2_initial.py @@ -21,7 +21,7 @@ import urllib from pathlib import Path -from renku.core.management import RENKU_HOME +from renku.core.constant import RENKU_HOME from renku.core.management.repository import DEFAULT_DATA_DIR as DATA_DIR from renku.core.migration.models.v3 import Collection, Dataset, Project, get_client_datasets from renku.core.migration.models.v9 import generate_file_id, generate_label diff --git a/renku/core/misc/__init__.py b/renku/core/misc/__init__.py new file mode 100644 index 0000000000..b4fcf2d675 --- /dev/null +++ b/renku/core/misc/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2017-2022 - Swiss Data Science Center (SDSC) +# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and +# Eidgenössische Technische Hochschule Zürich (ETHZ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Various management functionalities.""" diff --git a/renku/core/misc/gc.py b/renku/core/misc/gc.py new file mode 100644 index 0000000000..053c1b784a --- /dev/null +++ b/renku/core/misc/gc.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2020 - Swiss Data Science Center (SDSC) +# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and +# Eidgenössische Technische Hochschule Zürich (ETHZ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Project cleanup management.""" + +from renku.command.command_builder.command import inject +from renku.core.constant import CACHE, RENKU_HOME, RENKU_TMP +from renku.core.interface.client_dispatcher import IClientDispatcher + + +@inject.autoparams() +def remove_caches(client_dispatcher: IClientDispatcher): + """Remove caches and temporary files. + + Args: + client_dispatcher(IClientDispatcher): Injected client dispatcher. + + """ + client = client_dispatcher.current_client + + cache_paths = [CACHE, RENKU_TMP] + paths = [client.path / RENKU_HOME / p for p in cache_paths] + + client.repository.clean(paths=paths) diff --git a/renku/core/template/template.py b/renku/core/template/template.py index c70c4cdb3e..bdad2af67e 100644 --- a/renku/core/template/template.py +++ b/renku/core/template/template.py @@ -155,6 +155,7 @@ def copy_template_metadata_to_client(): except OSError as e: # TODO: Use a general cleanup strategy: https://github.com/SwissDataScienceCenter/renku-python/issues/736 if cleanup: + client.repository.reset(hard=True) client.repository.clean() raise errors.TemplateUpdateError(f"Cannot write to '{destination}'") from e diff --git a/renku/core/util/contexts.py b/renku/core/util/contexts.py index 46b776bb54..eace2bb1ef 100644 --- a/renku/core/util/contexts.py +++ b/renku/core/util/contexts.py @@ -106,7 +106,7 @@ def measure(message="TOTAL"): def click_context(path, command): """Provide a click context with repo path injected.""" - from renku.core.management import RENKU_HOME + from renku.core.constant import RENKU_HOME from renku.core.management.client import LocalClient return click.Context( diff --git a/renku/core/util/git.py b/renku/core/util/git.py index 96c1a4cc22..3da18963be 100644 --- a/renku/core/util/git.py +++ b/renku/core/util/git.py @@ -137,7 +137,7 @@ def get_cache_directory_for_repository(client, url) -> Path: Path: The path of the cache. """ - from renku.core.dataset.constant import CACHE + from renku.core.constant import CACHE return client.renku_path / CACHE / get_full_repository_path(url) diff --git a/renku/core/util/metadata.py b/renku/core/util/metadata.py index 7fa6cc0532..ad7cbd56ba 100644 --- a/renku/core/util/metadata.py +++ b/renku/core/util/metadata.py @@ -84,8 +84,8 @@ def construct_creator(creator: Union[dict, str], ignore_email) -> Tuple[Optional def is_external_file(path: Union[Path, str], client_path: Path): """Checks if a path is an external file.""" + from renku.core.constant import RENKU_HOME from renku.core.dataset.constant import POINTERS - from renku.core.management import RENKU_HOME path = client_path / path if not path.is_symlink() or not is_subpath(path=path, base=client_path): diff --git a/renku/core/workflow/plan_factory.py b/renku/core/workflow/plan_factory.py index 42d4e02737..9fc96e7830 100644 --- a/renku/core/workflow/plan_factory.py +++ b/renku/core/workflow/plan_factory.py @@ -31,9 +31,9 @@ from renku.command.command_builder.command import inject from renku.core import errors +from renku.core.constant import RENKU_HOME, RENKU_TMP from renku.core.interface.client_dispatcher import IClientDispatcher from renku.core.interface.project_gateway import IProjectGateway -from renku.core.management import RENKU_HOME from renku.core.util.git import is_path_safe from renku.core.util.metadata import is_external_file from renku.core.util.os import get_absolute_path, get_relative_path, is_subpath @@ -50,8 +50,6 @@ STARTED_AT = int(time.time() * 1000) -RENKU_TMP = "tmp" - class PlanFactory: """Factory for creating a plan from a command line call.""" diff --git a/renku/core/workflow/providers/toil.py b/renku/core/workflow/providers/toil.py index 5227731376..c82abc92bf 100644 --- a/renku/core/workflow/providers/toil.py +++ b/renku/core/workflow/providers/toil.py @@ -37,11 +37,10 @@ from renku.command.echo import progressbar from renku.core import errors +from renku.core.constant import RENKU_HOME, RENKU_TMP from renku.core.errors import WorkflowExecuteError -from renku.core.management.config import RENKU_HOME from renku.core.plugin import hookimpl from renku.core.plugin.provider import RENKU_ENV_PREFIX -from renku.core.workflow.plan_factory import RENKU_TMP from renku.domain_model.workflow.parameter import CommandParameterBase from renku.domain_model.workflow.plan import Plan from renku.domain_model.workflow.provider import IWorkflowProvider diff --git a/renku/domain_model/template.py b/renku/domain_model/template.py index c59ca6f203..1ad5ed3f96 100644 --- a/renku/domain_model/template.py +++ b/renku/domain_model/template.py @@ -29,7 +29,7 @@ import yaml from renku.core import errors -from renku.core.management import RENKU_HOME +from renku.core.constant import RENKU_HOME from renku.core.util.os import get_safe_relative_path, hash_file TEMPLATE_MANIFEST = "manifest.yaml" diff --git a/renku/infrastructure/repository.py b/renku/infrastructure/repository.py index 459b990c8d..788c4ac6c6 100644 --- a/renku/infrastructure/repository.py +++ b/renku/infrastructure/repository.py @@ -225,10 +225,9 @@ def checkout(self, reference: Union["Branch", "Tag", str]): """Check-out a specific reference.""" self.run_git_command("checkout", reference) - def clean(self): - """Remove all untracked files and reset the repo.""" - self.reset(hard=True) - self.run_git_command("clean", "-xdff") + def clean(self, paths: List[Union[Path, str]] = None): + """Remove untracked files.""" + self.run_git_command("clean", "-xdff", paths) def fetch( self, diff --git a/renku/ui/cli/__init__.py b/renku/ui/cli/__init__.py index 8eda9d4f75..0658e6391c 100644 --- a/renku/ui/cli/__init__.py +++ b/renku/ui/cli/__init__.py @@ -80,6 +80,7 @@ from renku.ui.cli.doctor import doctor from renku.ui.cli.env import env from renku.ui.cli.exception_handler import IssueFromTraceback +from renku.ui.cli.gc import gc from renku.ui.cli.githooks import githooks as githooks_command from renku.ui.cli.graph import graph from renku.ui.cli.init import init as init_command @@ -130,7 +131,7 @@ def _uuid_representer(dumper, data): def _is_renku_project(path: Path) -> bool: """Check if a path is a renku project.""" - from renku.core.management import RENKU_HOME + from renku.core.constant import RENKU_HOME from renku.core.management.repository import RepositoryApiMixin from renku.core.migration.utils import OLD_METADATA_PATH from renku.infrastructure.database import Database @@ -251,6 +252,7 @@ def help(ctx): cli.add_command(dataset) cli.add_command(doctor) cli.add_command(env) +cli.add_command(gc) cli.add_command(githooks_command) cli.add_command(graph) cli.add_command(init_command) diff --git a/renku/ui/cli/gc.py b/renku/ui/cli/gc.py new file mode 100644 index 0000000000..412d9c5e25 --- /dev/null +++ b/renku/ui/cli/gc.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2017-2022 - Swiss Data Science Center (SDSC) +# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and +# Eidgenössische Technische Hochschule Zürich (ETHZ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +r"""Free up disk space by removing temporary files and caches in a Renku project. + +.. cheatsheet:: + :group: Misc + :command: $ renku gc + :description: Free up disk space used for caches and temporary files. + :extended: +""" + +import click + + +@click.command() +def gc(): + """Cache and temporary files cleanup.""" + from renku.command.gc import gc_command + + gc_command().build().execute() diff --git a/renku/ui/service/controllers/api/mixins.py b/renku/ui/service/controllers/api/mixins.py index d2b0c7a921..877783a27b 100644 --- a/renku/ui/service/controllers/api/mixins.py +++ b/renku/ui/service/controllers/api/mixins.py @@ -24,8 +24,8 @@ import portalocker +from renku.core.constant import RENKU_HOME from renku.core.errors import GitCommandError, GitConfigurationError, RenkuException, UninitializedProject -from renku.core.management import RENKU_HOME from renku.core.util.contexts import click_context from renku.infrastructure.repository import Repository from renku.ui.service.cache.config import REDIS_NAMESPACE diff --git a/tests/cli/test_datasets.py b/tests/cli/test_datasets.py index 945124b74b..d598ec192c 100644 --- a/tests/cli/test_datasets.py +++ b/tests/cli/test_datasets.py @@ -29,11 +29,11 @@ from renku.command.format.dataset_files import DATASET_FILES_COLUMNS, DATASET_FILES_FORMATS from renku.command.format.datasets import DATASETS_COLUMNS, DATASETS_FORMATS from renku.core import errors +from renku.core.constant import RENKU_HOME from renku.core.dataset.constant import renku_pointers_path from renku.core.dataset.providers import ProviderFactory from renku.core.dataset.providers.dataverse import DataverseProvider from renku.core.dataset.providers.zenodo import ZenodoProvider -from renku.core.management.config import RENKU_HOME from renku.core.management.repository import DEFAULT_DATA_DIR as DATA_DIR from renku.core.util.urls import get_slug from renku.domain_model.dataset import Dataset diff --git a/tests/cli/test_errors.py b/tests/cli/test_errors.py index 353f2e16ee..f5445d7775 100644 --- a/tests/cli/test_errors.py +++ b/tests/cli/test_errors.py @@ -32,6 +32,7 @@ ["config"], ["dataset"], ["doctor"], + ["gc"], ["githooks"], ["graph", "export"], ["migrate"], diff --git a/tests/cli/test_gc.py b/tests/cli/test_gc.py new file mode 100644 index 0000000000..f5545ac1db --- /dev/null +++ b/tests/cli/test_gc.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2017-2022 - Swiss Data Science Center (SDSC) +# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and +# Eidgenössische Technische Hochschule Zürich (ETHZ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Test ``gc`` command.""" + +from renku.core.constant import CACHE, RENKU_HOME, RENKU_TMP +from renku.ui.cli import cli +from tests.utils import format_result_exception + + +def test_gc(runner, client): + """Test clean caches and temporary files.""" + # NOTE: Mock caches + tmp = client.path / RENKU_HOME / RENKU_TMP + tmp.mkdir(parents=True, exist_ok=True) + (tmp / "temp-file").touch() + cache = client.path / RENKU_HOME / CACHE + cache.mkdir(parents=True, exist_ok=True) + (tmp / "cache").touch() + + (client.path / "tracked").write_text("tracked file") + client.repository.add("tracked") + + (client.path / "untracked").write_text("untracked file") + + commit_sha_before = client.repository.head.commit.hexsha + + result = runner.invoke(cli, ["gc"]) + + commit_sha_after = client.repository.head.commit.hexsha + + assert 0 == result.exit_code, format_result_exception(result) + assert not tmp.exists() + assert not cache.exists() + assert "tracked" in [f.a_path for f in client.repository.staged_changes] + assert "untracked" in client.repository.untracked_files + assert commit_sha_after == commit_sha_before diff --git a/tests/cli/test_gitignore.py b/tests/cli/test_gitignore.py index 4103c820d7..144a063c16 100644 --- a/tests/cli/test_gitignore.py +++ b/tests/cli/test_gitignore.py @@ -36,6 +36,7 @@ def test_dataset_add(tmpdir, runner, client, subdirectory): assert 1 == result.exit_code + client.repository.reset(hard=True) client.repository.clean() # Use the --force ;) diff --git a/tests/cli/test_migrate.py b/tests/cli/test_migrate.py index 9aceb9ab86..d3d022dd19 100644 --- a/tests/cli/test_migrate.py +++ b/tests/cli/test_migrate.py @@ -23,11 +23,10 @@ import pytest +from renku.core.constant import RENKU_HOME, RENKU_TMP from renku.core.dataset.datasets_provenance import DatasetsProvenance -from renku.core.management import RENKU_HOME from renku.core.management.client import LocalClient from renku.core.management.migrate import SUPPORTED_PROJECT_VERSION, get_migrations -from renku.core.workflow.plan_factory import RENKU_TMP from renku.domain_model.dataset import RemoteEntity from renku.infrastructure.gateway.dataset_gateway import DatasetGateway from renku.infrastructure.repository import Repository