Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle dirty local module repos by force checkout of commits and branches if needed #2734

Merged
merged 11 commits into from
Feb 13, 2024
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

### Modules

- Handle dirty local module repos by force checkout of commits and branches if needed ([#2734](https://github.com/nf-core/tools/pull/2734))

### General

- fix ignoring changes in partially templated files (e.g. `.gitignore`) ([#2722](https://github.com/nf-core/tools/pull/2722))
Expand Down
26 changes: 24 additions & 2 deletions nf_core/synced_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,18 @@ def checkout_branch(self):
"""
Checks out the specified branch of the repository
"""
self.repo.git.checkout(self.branch)
try:
self.repo.git.checkout(self.branch)
except GitCommandError as e:
if (
self.fullname
and "modules" in self.fullname
and "Your local changes to the following files would be overwritten by checkout" in str(e)
):
log.debug(f"Overwriting local changes in '{self.local_repo_dir}'")
self.repo.git.checkout(self.branch, force=True)
else:
raise e

def checkout(self, commit):
"""
Expand All @@ -217,7 +228,18 @@ def checkout(self, commit):
Args:
commit (str): Git SHA of the commit
"""
self.repo.git.checkout(commit)
try:
self.repo.git.checkout(commit)
except GitCommandError as e:
if (
self.fullname
and "modules" in self.fullname
and "Your local changes to the following files would be overwritten by checkout" in str(e)
):
log.debug(f"Overwriting local changes in '{self.local_repo_dir}'")
self.repo.git.checkout(self.branch, force=True)
else:
raise e

def component_exists(self, component_name, component_type, checkout=True, commit=None):
"""
Expand Down
25 changes: 12 additions & 13 deletions tests/modules/modules_json.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import copy
import json
import os
import shutil
from pathlib import Path

Expand All @@ -16,7 +15,7 @@

def test_get_modules_json(self):
"""Checks that the get_modules_json function returns the correct result"""
mod_json_path = os.path.join(self.pipeline_dir, "modules.json")
mod_json_path = Path(self.pipeline_dir, "modules.json")
with open(mod_json_path) as fh:
try:
mod_json_sb = json.load(fh)
Expand Down Expand Up @@ -49,16 +48,16 @@ def test_mod_json_update(self):

def test_mod_json_create(self):
"""Test creating a modules.json file from scratch"""
mod_json_path = os.path.join(self.pipeline_dir, "modules.json")
mod_json_path = Path(self.pipeline_dir, "modules.json")
# Remove the existing modules.json file
os.remove(mod_json_path)
mod_json_path.unlink()

# Create the new modules.json file
# (There are no prompts as long as there are only nf-core modules)
ModulesJson(self.pipeline_dir).create()

# Check that the file exists
assert os.path.exists(mod_json_path)
assert (mod_json_path).exists()

# Get the contents of the file
mod_json_obj = ModulesJson(self.pipeline_dir)
Expand Down Expand Up @@ -94,7 +93,7 @@ def test_mod_json_create_with_patch(self):
patch_obj.patch("fastqc")

# Remove the existing modules.json file
os.remove(mod_json_path)
mod_json_path.unlink()

# Create the new modules.json file
ModulesJson(self.pipeline_dir).create()
Expand Down Expand Up @@ -137,7 +136,7 @@ def test_mod_json_up_to_date_module_removed(self):
but is missing in the pipeline
"""
# Remove the fastqc module
fastqc_path = os.path.join(self.pipeline_dir, "modules", NF_CORE_MODULES_NAME, "fastqc")
fastqc_path = Path(self.pipeline_dir, "modules", NF_CORE_MODULES_NAME, "fastqc")
shutil.rmtree(fastqc_path)

# Check that the modules.json file is up to date, and reinstall the module
Expand All @@ -146,9 +145,9 @@ def test_mod_json_up_to_date_module_removed(self):

# Check that the module has been reinstalled
files = ["main.nf", "meta.yml"]
assert os.path.exists(fastqc_path)
assert fastqc_path.exists()
for f in files:
assert os.path.exists(os.path.join(fastqc_path, f))
assert Path(fastqc_path, f).exists()


def test_mod_json_up_to_date_reinstall_fails(self):
Expand All @@ -161,7 +160,7 @@ def test_mod_json_up_to_date_reinstall_fails(self):
mod_json_obj.update("modules", ModulesRepo(), "fastqc", "INVALID_GIT_SHA", "modules", write_file=True)

# Remove the fastqc module
fastqc_path = os.path.join(self.pipeline_dir, "modules", NF_CORE_MODULES_NAME, "fastqc")
fastqc_path = Path(self.pipeline_dir, "modules", NF_CORE_MODULES_NAME, "fastqc")
shutil.rmtree(fastqc_path)

# Check that the modules.json file is up to date, and remove the fastqc module entry
Expand Down Expand Up @@ -206,12 +205,12 @@ def test_mod_json_dump(self):
mod_json_obj = ModulesJson(self.pipeline_dir)
mod_json = mod_json_obj.get_modules_json()
# Remove the modules.json file
mod_json_path = os.path.join(self.pipeline_dir, "modules.json")
os.remove(mod_json_path)
mod_json_path = Path(self.pipeline_dir, "modules.json")
mod_json_path.unlink()

# Check that the dump function creates the file
mod_json_obj.dump()
assert os.path.exists(mod_json_path)
assert mod_json_path.exists()

# Check that the dump function writes the correct content
with open(mod_json_path) as f:
Expand Down
Loading