Repository: nf-core/tools

Issue:
nf-core modules update changed md5sum of skipped module in modules.json
### Description of the bug

Hey!

I ran `nf-core modules update -a` and then selected the second option (show diff and y/N before applying it). For two modules the md5sum was changed, even though I selected N and skipped the update:

see here:

https://github.com/nf-core/sarek/pull/822/files#diff-97c7fe3fe8f628d2435d00b93af4cb47052e8e1f3d33b7334d1a031fd15415d7

### Command used and terminal output

```console
nf-core modules update -a
```


### System information

Using nf-core/tools 2.6


Discussion:

Resolving patch:
diff --git a/nf_core/modules/update.py b/nf_core/modules/update.py
--- a/nf_core/modules/update.py
+++ b/nf_core/modules/update.py
@@ -173,7 +173,7 @@ def update(self, module=None):
 
             if patch_relpath is not None:
                 patch_successful = self.try_apply_patch(
-                    module, modules_repo.repo_path, patch_relpath, module_dir, module_install_dir
+                    module, modules_repo.repo_path, patch_relpath, module_dir, module_install_dir, write_file=False
                 )
                 if patch_successful:
                     log.info(f"Module '{module_fullname}' patched successfully")
@@ -630,7 +630,7 @@ def move_files_from_tmp_dir(self, module, install_folder, repo_path, new_version
         log.info(f"Updating '{repo_path}/{module}'")
         log.debug(f"Updating module '{module}' to {new_version} from {repo_path}")
 
-    def try_apply_patch(self, module, repo_path, patch_relpath, module_dir, module_install_dir):
+    def try_apply_patch(self, module, repo_path, patch_relpath, module_dir, module_install_dir, write_file=True):
         """
         Try applying a patch file to the new module files
 
@@ -698,7 +698,7 @@ def try_apply_patch(self, module, repo_path, patch_relpath, module_dir, module_i
 
         # Add the patch file to the modules.json file
         self.modules_json.add_patch_entry(
-            module, self.modules_repo.remote_url, repo_path, patch_relpath, write_file=True
+            module, self.modules_repo.remote_url, repo_path, patch_relpath, write_file=write_file
         )
 
         return True


Test patch:
diff --git a/tests/modules/update.py b/tests/modules/update.py
--- a/tests/modules/update.py
+++ b/tests/modules/update.py
@@ -2,13 +2,17 @@
 import os
 import shutil
 import tempfile
+from pathlib import Path
+from unittest import mock
 
+import questionary
 import yaml
 
 import nf_core.utils
 from nf_core.modules.install import ModuleInstall
 from nf_core.modules.modules_json import ModulesJson
 from nf_core.modules.modules_repo import NF_CORE_MODULES_NAME, NF_CORE_MODULES_REMOTE
+from nf_core.modules.patch import ModulePatch
 from nf_core.modules.update import ModuleUpdate
 
 from ..utils import (
@@ -288,6 +292,73 @@ def test_update_different_branch_mix_modules_branch_test(self):
     assert modules_json.get_module_version("multiqc", GITLAB_URL, GITLAB_REPO) == GITLAB_BRANCH_TEST_NEW_SHA
 
 
+# Mock questionary answer: do not update module, only show diffs
+@mock.patch.object(questionary.Question, "unsafe_ask", return_value=False)
+def test_update_only_show_differences(self, mock_prompt):
+    """Try updating all modules showing differences.
+    Don't update some of them.
+    Check that the sha in modules.json is not changed."""
+    modules_json = ModulesJson(self.pipeline_dir)
+    update_obj = ModuleUpdate(self.pipeline_dir, update_all=True, show_diff=True)
+
+    tmpdir = tempfile.mkdtemp()
+    shutil.rmtree(tmpdir)
+    shutil.copytree(Path(self.pipeline_dir, "modules", NF_CORE_MODULES_NAME), tmpdir)
+
+    assert update_obj.update() is True
+
+    mod_json = modules_json.get_modules_json()
+    # Loop through all modules and check that they are NOT updated (according to the modules.json file)
+    # Modules that can be updated but shouldn't are custom/dumpsoftwareversions and fastqc
+    # Module multiqc is already up to date so don't check
+    for mod in ["custom/dumpsoftwareversions", "fastqc"]:
+        correct_git_sha = list(update_obj.modules_repo.get_component_git_log(mod, "modules", depth=1))[0]["git_sha"]
+        current_git_sha = mod_json["repos"][NF_CORE_MODULES_REMOTE]["modules"][NF_CORE_MODULES_NAME][mod]["git_sha"]
+        assert correct_git_sha != current_git_sha
+        assert cmp_module(Path(tmpdir, mod), Path(self.pipeline_dir, "modules", NF_CORE_MODULES_NAME, mod)) is True
+
+
+# Mock questionary answer: do not update module, only show diffs
+@mock.patch.object(questionary.Question, "unsafe_ask", return_value=False)
+def test_update_only_show_differences_when_patch(self, mock_prompt):
+    """Try updating all modules showing differences when there's a patched module.
+    Don't update some of them.
+    Check that the sha in modules.json is not changed."""
+    modules_json = ModulesJson(self.pipeline_dir)
+    update_obj = ModuleUpdate(self.pipeline_dir, update_all=True, show_diff=True)
+
+    # Modify fastqc module, it will have a patch which will be applied during update
+    # We modify fastqc because it's one of the modules that can be updated and there's another one before it (custom/dumpsoftwareversions)
+    module_path = Path(self.pipeline_dir, "modules", "nf-core", "fastqc")
+    main_path = Path(module_path, "main.nf")
+    with open(main_path, "r") as fh:
+        lines = fh.readlines()
+    for line_index in range(len(lines)):
+        if lines[line_index] == "    label 'process_medium'\n":
+            lines[line_index] = "    label 'process_low'\n"
+            break
+    with open(main_path, "w") as fh:
+        fh.writelines(lines)
+    # Create a patch file
+    patch_obj = ModulePatch(self.pipeline_dir)
+    patch_obj.patch("fastqc")
+    # Check that a patch file with the correct name has been created
+    assert set(os.listdir(module_path)) == {"main.nf", "meta.yml", "fastqc.diff"}
+
+    # Update all modules
+    assert update_obj.update() is True
+
+    mod_json = modules_json.get_modules_json()
+    # Loop through all modules and check that they are NOT updated (according to the modules.json file)
+    # Modules that can be updated but shouldn't are custom/dumpsoftwareversions and fastqc
+    # Module multiqc is already up to date so don't check
+    for mod in ["custom/dumpsoftwareversions", "fastqc"]:
+        correct_git_sha = list(update_obj.modules_repo.get_component_git_log(mod, "modules", depth=1))[0]["git_sha"]
+        current_git_sha = mod_json["repos"][NF_CORE_MODULES_REMOTE]["modules"][NF_CORE_MODULES_NAME][mod]["git_sha"]
+        print(correct_git_sha, current_git_sha)
+        assert correct_git_sha != current_git_sha
+
+
 def cmp_module(dir1, dir2):
     """Compare two versions of the same module"""
     files = ["main.nf", "meta.yml"]
diff --git a/tests/test_modules.py b/tests/test_modules.py
--- a/tests/test_modules.py
+++ b/tests/test_modules.py
@@ -200,6 +200,8 @@ def test_modulesrepo_class(self):
         test_update_different_branch_mix_modules_branch_test,
         test_update_different_branch_mixed_modules_main,
         test_update_different_branch_single_module,
+        test_update_only_show_differences,
+        test_update_only_show_differences_when_patch,
         test_update_with_config_dont_update,
         test_update_with_config_fix_all,
         test_update_with_config_fixed_version,