nf-core / tools

Python package with helper tools for the nf-core community.
https://nf-co.re
MIT License
241 stars 190 forks source link

Module update fails if there is a new file (even if module is patched) #2749

Closed IreneRobles closed 8 months ago

IreneRobles commented 9 months ago

Description of the bug

Hi everyone!

I am unable to update a module with nf-core modules update, even if the module has been patched with nf-core modules patch if the change I introduce is a new file in the folder, such as a nextflow.config

It would be nice if I could update the modules without reinstalling them when I add files.

Command used and terminal output

$ tree modules/nf-core/multiqc
modules/nf-core/multiqc
├── environment.yml
├── main.nf
├── meta.yml
├── nextflow.config
└── tests
    ├── main.nf.test
    ├── main.nf.test.snap
    └── tags.yml

$ nf-core modules patch multiqc

$ tree modules/nf-core/multiqc
modules/nf-core/multiqc
├── environment.yml
├── main.nf
├── meta.yml
├── multiqc.diff
├── nextflow.config
└── tests
    ├── main.nf.test
    ├── main.nf.test.snap
    └── tags.yml
$ nf-core modules update multiqc

                                          ,--./,-.
          ___     __   __   __   ___     /,-._.--~\
    |\ | |__  __ /  ` /  \ |__) |__         }  {
    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
                                          `._,._,'

    nf-core/tools version 2.12.1 - https://nf-co.re

? Do you want to view diffs of the proposed changes? No previews, just update everything
INFO     Found patch for  module 'nf-core/multiqc'. Trying to apply it to new files                                              
INFO     Modules multiqc contains a patch file.                                                                                  
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/ec2-user/miniconda3/envs/nf-core/bin/nf-core:10 in <module>                                │
│                                                                                                  │
│    7                                                                                             │
│    8 if __name__ == '__main__':                                                                  │
│    9 │   sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])                       │
│ ❱ 10 │   sys.exit(run_nf_core())                                                                 │
│   11                                                                                             │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/nf_core/__main__.py:141 in    │
│ run_nf_core                                                                                      │
│                                                                                                  │
│    138 │   │   │   log.debug(f"Could not check latest version: {e}")                             │
│    139 │   │   stderr.print("\n")                                                                │
│    140 │   # Launch the click cli                                                                │
│ ❱  141 │   nf_core_cli(auto_envvar_prefix="NFCORE")                                              │
│    142                                                                                           │
│    143                                                                                           │
│    144 @tui()                                                                                    │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/click/core.py:1157 in         │
│ __call__                                                                                         │
│                                                                                                  │
│   1154 │                                                                                         │
│   1155 │   def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any:                           │
│   1156 │   │   """Alias for :meth:`main`."""                                                     │
│ ❱ 1157 │   │   return self.main(*args, **kwargs)                                                 │
│   1158                                                                                           │
│   1159                                                                                           │
│   1160 class Command(BaseCommand):                                                               │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/rich_click/rich_command.py:12 │
│ 6 in main                                                                                        │
│                                                                                                  │
│   123 │   │   try:                                                                               │
│   124 │   │   │   try:                                                                           │
│   125 │   │   │   │   with self.make_context(prog_name, args, **extra) as ctx:                   │
│ ❱ 126 │   │   │   │   │   rv = self.invoke(ctx)                                                  │
│   127 │   │   │   │   │   if not standalone_mode:                                                │
│   128 │   │   │   │   │   │   return rv                                                          │
│   129 │   │   │   │   │   # it's not safe to `ctx.exit(rv)` here!                                │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/click/core.py:1688 in invoke  │
│                                                                                                  │
│   1685 │   │   │   │   super().invoke(ctx)                                                       │
│   1686 │   │   │   │   sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)                    │
│   1687 │   │   │   │   with sub_ctx:                                                             │
│ ❱ 1688 │   │   │   │   │   return _process_result(sub_ctx.command.invoke(sub_ctx))               │
│   1689 │   │                                                                                     │
│   1690 │   │   # In chain mode we create the contexts step by step, but after the                │
│   1691 │   │   # base command has been invoked.  Because at that point we do not                 │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/click/core.py:1688 in invoke  │
│                                                                                                  │
│   1685 │   │   │   │   super().invoke(ctx)                                                       │
│   1686 │   │   │   │   sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)                    │
│   1687 │   │   │   │   with sub_ctx:                                                             │
│ ❱ 1688 │   │   │   │   │   return _process_result(sub_ctx.command.invoke(sub_ctx))               │
│   1689 │   │                                                                                     │
│   1690 │   │   # In chain mode we create the contexts step by step, but after the                │
│   1691 │   │   # base command has been invoked.  Because at that point we do not                 │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/click/core.py:1434 in invoke  │
│                                                                                                  │
│   1431 │   │   │   echo(style(message, fg="red"), err=True)                                      │
│   1432 │   │                                                                                     │
│   1433 │   │   if self.callback is not None:                                                     │
│ ❱ 1434 │   │   │   return ctx.invoke(self.callback, **ctx.params)                                │
│   1435 │                                                                                         │
│   1436 │   def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:  │
│   1437 │   │   """Return a list of completions for the incomplete value. Looks                   │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/click/core.py:783 in invoke   │
│                                                                                                  │
│    780 │   │                                                                                     │
│    781 │   │   with augment_usage_errors(__self):                                                │
│    782 │   │   │   with ctx:                                                                     │
│ ❱  783 │   │   │   │   return __callback(*args, **kwargs)                                        │
│    784 │                                                                                         │
│    785 │   def forward(                                                                          │
│    786 │   │   __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any  # noqa: B902             │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/click/decorators.py:33 in     │
│ new_func                                                                                         │
│                                                                                                  │
│    30 │   """                                                                                    │
│    31 │                                                                                          │
│    32 │   def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R":                            │
│ ❱  33 │   │   return f(get_current_context(), *args, **kwargs)                                   │
│    34 │                                                                                          │
│    35 │   return update_wrapper(new_func, f)                                                     │
│    36                                                                                            │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/nf_core/__main__.py:912 in    │
│ modules_update                                                                                   │
│                                                                                                  │
│    909 │   │   │   ctx.obj["modules_repo_branch"],                                               │
│    910 │   │   │   ctx.obj["modules_repo_no_pull"],                                              │
│    911 │   │   )                                                                                 │
│ ❱  912 │   │   exit_status = module_install.update(tool)                                         │
│    913 │   │   if not exit_status and install_all:                                               │
│    914 │   │   │   sys.exit(1)                                                                   │
│    915 │   except (UserWarning, LookupError) as e:                                               │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/nf_core/components/update.py: │
│ 196 in update                                                                                    │
│                                                                                                  │
│   193 │   │   │   │   continue                                                                   │
│   194 │   │   │                                                                                  │
│   195 │   │   │   if patch_relpath is not None:                                                  │
│ ❱ 196 │   │   │   │   patch_successful = self.try_apply_patch(                                   │
│   197 │   │   │   │   │   component,                                                             │
│   198 │   │   │   │   │   modules_repo.repo_path,                                                │
│   199 │   │   │   │   │   patch_relpath,                                                         │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/nf_core/components/update.py: │
│ 788 in try_apply_patch                                                                           │
│                                                                                                  │
│   785 │   │   shutil.copytree(component_install_dir, temp_component_dir)                         │
│   786 │   │                                                                                      │
│   787 │   │   try:                                                                               │
│ ❱ 788 │   │   │   new_files = ModulesDiffer.try_apply_patch(component, repo_path, patch_path,    │
│   789 │   │   except LookupError:                                                                │
│   790 │   │   │   # Patch failed. Save the patch file by moving to the install dir               │
│   791 │   │   │   shutil.move(patch_path, Path(component_install_dir, patch_path.relative_to(c   │
│                                                                                                  │
│ /home/ec2-user/miniconda3/envs/nf-core/lib/python3.8/site-packages/nf_core/modules/modules_diffe │
│ r.py:450 in try_apply_patch                                                                      │
│                                                                                                  │
│   447 │   │   │   log.debug(f"Applying patch to {file}")                                         │
│   448 │   │   │   fn = Path(file).relative_to(module_relpath)                                    │
│   449 │   │   │   file_path = module_dir / fn                                                    │
│ ❱ 450 │   │   │   with open(file_path) as fh:                                                    │
│   451 │   │   │   │   file_lines = fh.readlines()                                                │
│   452 │   │   │   patched_new_lines = ModulesDiffer.try_apply_single_patch(file_lines, patch,    │
│   453 │   │   │   new_files[str(fn)] = patched_new_lines                                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpyqidsy9u/multiqc/nextflow.config'

System information

Nextflow version: 23.10.1.5891 Hardware: AWS EC2 t2.2xlarge Executor: local OS: Amazon Linux Version of nf-core/tools: 2.12.1 Python version: 3.8.18

mirpedrol commented 8 months ago

done by #2771