Skip to content

Commit 43d5f3b

Browse files
committed
Automated clean up
1 parent b80168e commit 43d5f3b

2 files changed

Lines changed: 78 additions & 35 deletions

File tree

src/hermes/commands/init/base.py

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ def string_in_file(file_path, search_string: str) -> bool:
123123

124124

125125
def get_builtin_plugins(plugin_commands: list[str]) -> dict[str: HermesPlugin]:
126-
"""Returns a list of installed HermesPlugins based on a list of related command names."""
126+
"""
127+
Returns a list of installed HermesPlugins based on a list of related command names.
128+
This is currently not used (we use the marketplace code instead) but maybe later.
129+
"""
127130
plugins = {}
128131
for plugin_command_name in plugin_commands:
129132
entry_point_group = f"hermes.{plugin_command_name}"
@@ -159,6 +162,7 @@ def __init__(self, parser: argparse.ArgumentParser):
159162
super().__init__(parser)
160163
self.folder_info: HermesInitFolderInfo = HermesInitFolderInfo()
161164
self.hermes_was_already_installed: bool = False
165+
self.new_created_paths: list[Path] = []
162166
self.tokens: dict = {}
163167
self.setup_method: str = ""
164168
self.deposit_platform: DepositPlatform = DepositPlatform.Empty
@@ -260,19 +264,22 @@ def __call__(self, args: argparse.Namespace) -> None:
260264
sc.next_step("Connect with git hoster")
261265
self.configure_git_project()
262266

267+
self.clean_up_files(False)
263268
sc.echo("\nHERMES is now initialized and ready to be used.\n",
264269
formatting=sc.Formats.OKGREEN+sc.Formats.BOLD)
265270

266271
# Nice message on Ctrl+C
267272
except KeyboardInterrupt:
268273
sc.echo("HERMES init was aborted.", sc.Formats.WARNING)
274+
self.clean_up_files(True)
269275
sys.exit()
270276

271277
# Useful message on error
272278
except Exception as e:
273279
sc.echo(f"An error occurred during execution of HERMES init: {e}",
274280
formatting=sc.Formats.FAIL+sc.Formats.BOLD)
275281
sc.debug_info(traceback.format_exc())
282+
self.clean_up_files(True)
276283
sys.exit(2)
277284

278285
def test_initialization(self) -> None:
@@ -344,9 +351,11 @@ def test_initialization(self) -> None:
344351

345352
def create_hermes_toml(self) -> None:
346353
"""Creates the hermes.toml file based on a self.hermes_toml_data"""
354+
hermes_toml_path = Path("hermes.toml")
355+
self.mark_as_new_path(hermes_toml_path)
347356
if (not self.folder_info.has_hermes_toml) \
348357
or sc.confirm("Do you want to replace your `hermes.toml` with a new one?", default=True):
349-
with open('hermes.toml', 'w') as toml_file:
358+
with open(hermes_toml_path, 'w') as toml_file:
350359
# noinspection PyTypeChecker
351360
toml.dump(self.hermes_toml_data, toml_file)
352361
sc.echo("`hermes.toml` was created.", formatting=sc.Formats.OKGREEN)
@@ -377,17 +386,19 @@ def create_citation_cff(self) -> None:
377386

378387
def update_gitignore(self) -> None:
379388
"""Creates .gitignore if there is none and adds '.hermes' to it"""
389+
gitignore_path = Path(".gitignore")
390+
self.mark_as_new_path(gitignore_path)
380391
if not self.folder_info.has_gitignore:
381-
open(".gitignore", 'w')
392+
open(gitignore_path, 'w')
382393
sc.echo("A new `.gitignore` file was created.", formatting=sc.Formats.OKGREEN)
383394
self.refresh_folder_info()
384395
if self.folder_info.has_gitignore:
385-
with open(".gitignore", "r") as file:
396+
with open(gitignore_path, "r") as file:
386397
gitignore_lines = file.readlines()
387398
if any([line.startswith(".hermes") for line in gitignore_lines]):
388399
sc.echo("The `.gitignore` file already contains `.hermes/`")
389400
else:
390-
with open(".gitignore", "a") as file:
401+
with open(gitignore_path, "a") as file:
391402
file.write("# Ignoring all HERMES cache files\n")
392403
file.write(".hermes/\n")
393404
file.write("hermes.log\n")
@@ -403,19 +414,28 @@ def create_ci_template(self) -> None:
403414
match self.git_hoster:
404415
case GitHoster.GitHub:
405416
template_url = self.get_template_url("TEMPLATE_hermes_github_to_zenodo.yml")
406-
ci_file_folder = ".github/workflows"
417+
ci_file_folder = Path(".github/workflows")
407418
ci_file_name = "hermes_github.yml"
408-
Path(ci_file_folder).mkdir(parents=True, exist_ok=True)
419+
self.mark_as_new_path(ci_file_folder)
420+
ci_file_folder.mkdir(parents=True, exist_ok=True)
409421
ci_file_path = Path(ci_file_folder) / ci_file_name
422+
self.mark_as_new_path(ci_file_path)
410423
download_file_from_url(template_url, ci_file_path)
411424
self.configure_ci_template(ci_file_path)
412425
sc.echo(f"GitHub CI: File was created at {ci_file_path}", formatting=sc.Formats.OKGREEN)
413426
case GitHoster.GitLab:
414427
gitlab_ci_template_url = self.get_template_url("TEMPLATE_hermes_gitlab_to_zenodo.yml")
415428
hermes_ci_template_url = self.get_template_url("hermes-ci.yml")
416429
gitlab_ci_path = Path(".gitlab-ci.yml")
417-
Path("gitlab").mkdir(parents=True, exist_ok=True)
418-
hermes_ci_path = Path("gitlab") / "hermes-ci.yml"
430+
gitlab_folder_path = Path("gitlab")
431+
hermes_ci_path = gitlab_folder_path / "hermes-ci.yml"
432+
# Adding paths to our list
433+
self.mark_as_new_path(gitlab_ci_path)
434+
self.mark_as_new_path(gitlab_folder_path)
435+
self.mark_as_new_path(hermes_ci_path)
436+
# Creating the gitlab folder
437+
gitlab_folder_path.mkdir(parents=True, exist_ok=True)
438+
# Creating / updating gitlab-ci
419439
if gitlab_ci_path.exists():
420440
if string_in_file(gitlab_ci_path, "hermes-ci.yml"):
421441
sc.echo(f"It seems like your {gitlab_ci_path} file is already configured for hermes.")
@@ -426,6 +446,7 @@ def create_ci_template(self) -> None:
426446
download_file_from_url(gitlab_ci_template_url, gitlab_ci_path)
427447
sc.echo(f"GitLab CI: {gitlab_ci_path} was created.", formatting=sc.Formats.OKGREEN)
428448
self.configure_ci_template(gitlab_ci_path)
449+
# Creating hermes-ci
429450
download_file_from_url(hermes_ci_template_url, hermes_ci_path)
430451
self.configure_ci_template(hermes_ci_path)
431452

@@ -618,7 +639,7 @@ def connect_deposit_platform(self) -> None:
618639
connect_zenodo.setup(using_sandbox=True)
619640
self.create_zenodo_token()
620641

621-
def choose_plugins(self):
642+
def choose_plugins(self) -> None:
622643
"""User chooses the plugins he wants to use."""
623644
plugin_infos: list[marketplace.PluginInfo] = marketplace.get_plugin_infos()
624645
plugins_builtin: list[marketplace.PluginInfo] = list(filter(lambda p: p.builtin, plugin_infos))
@@ -654,7 +675,7 @@ def choose_plugins(self):
654675
chosen_plugin = plugins_available.pop(choice - 1)
655676
plugins_selected.append(chosen_plugin)
656677

657-
def integrate_plugins(self):
678+
def integrate_plugins(self) -> None:
658679
"""
659680
Plugin installation is added to the ci-parameters.
660681
Also for now we use this method to do custom plugin installation steps.
@@ -688,6 +709,7 @@ def no_git_setup(self, start_question: str = "") -> None:
688709
sc.next_step("Create CITATION.cff file")
689710
self.create_citation_cff()
690711

712+
self.clean_up_files(False)
691713
sc.echo("\nHERMES is now initialized (without git integration or CI/CD files).\n",
692714
formatting=sc.Formats.OKGREEN)
693715

@@ -758,6 +780,27 @@ def choose_deposit_files(self) -> None:
758780
for file in self.folder_info.dir_list:
759781
sc.echo(f"\t\t{file}", formatting=sc.Formats.OKCYAN)
760782

761-
def clean_up_files(self):
762-
if not self.hermes_was_already_installed:
763-
pass
783+
def mark_as_new_path(self, path: Path, avoid_existing: bool = True) -> None:
784+
"""
785+
This method should be called directly BEFORE creating a new file in the given Path.
786+
This way we can look if something already exists there to decide later-on if we want to delete it on abort.
787+
"""
788+
if (not avoid_existing) or (not path.exists()):
789+
self.new_created_paths.append(path)
790+
791+
def clean_up_files(self, aborted: bool) -> None:
792+
"""
793+
This gets called when init is finished (successfully or aborted).
794+
It cleans up unwanted files (like .hermes folder) and everything new when aborted.
795+
"""
796+
os.remove(Path(".hermes"))
797+
if aborted:
798+
if not self.hermes_was_already_installed:
799+
for path in reversed(self.new_created_paths):
800+
try:
801+
if path.is_dir():
802+
path.rmdir()
803+
else:
804+
os.remove(path)
805+
except Exception as e:
806+
sc.echo(f"Cleaning Warning: Could not remove {path}. ({e})")

src/hermes/commands/marketplace.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -153,27 +153,6 @@ def _plugin_loc(_plugin: SchemaOrgSoftwareApplication) -> str:
153153
return "builtin" if _plugin.is_part_of == schema_org_hermes else (_plugin.url or "")
154154

155155

156-
def get_plugin_infos() -> list[PluginInfo]:
157-
response = requests.get(MARKETPLACE_URL, headers={"User-Agent": hermes_user_agent})
158-
response.raise_for_status()
159-
parser = PluginMarketPlaceParser()
160-
parser.feed(response.text)
161-
infos: list[PluginInfo] = []
162-
if parser.plugins:
163-
plugins_sorted = _sort_plugins_by_step(parser.plugins)
164-
for step in plugins_sorted.keys():
165-
for plugin in plugins_sorted[step]:
166-
info = PluginInfo()
167-
info.name = plugin.name
168-
info.step = step
169-
info.location = _plugin_loc(plugin)
170-
info.builtin = plugin.is_part_of == schema_org_hermes
171-
info.install_url = plugin.install_url
172-
info.abstract = plugin.abstract
173-
infos.append(info)
174-
return infos
175-
176-
177156
def main():
178157
response = requests.get(MARKETPLACE_URL, headers={"User-Agent": hermes_user_agent})
179158
response.raise_for_status()
@@ -248,3 +227,24 @@ def is_valid(self) -> bool:
248227
to make sure that other things are valid too.
249228
"""
250229
return self.get_pip_install_command() != ""
230+
231+
232+
def get_plugin_infos() -> list[PluginInfo]:
233+
response = requests.get(MARKETPLACE_URL, headers={"User-Agent": hermes_user_agent})
234+
response.raise_for_status()
235+
parser = PluginMarketPlaceParser()
236+
parser.feed(response.text)
237+
infos: list[PluginInfo] = []
238+
if parser.plugins:
239+
plugins_sorted = _sort_plugins_by_step(parser.plugins)
240+
for step in plugins_sorted.keys():
241+
for plugin in plugins_sorted[step]:
242+
info = PluginInfo()
243+
info.name = plugin.name
244+
info.step = step
245+
info.location = _plugin_loc(plugin)
246+
info.builtin = plugin.is_part_of == schema_org_hermes
247+
info.install_url = plugin.install_url
248+
info.abstract = plugin.abstract
249+
infos.append(info)
250+
return infos

0 commit comments

Comments
 (0)