We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`create`: check HTML response is 200 when fetching logo
### Description of the bug

After an automated sync of the nf-core tools v2.2, the dark logo for Epitopeprediction was not created and instead this was inside that file:

```html 
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>507 Insufficient Storage</title>
</head><body>
<h1>Insufficient Storage</h1>
<p>The method could not be performed on the resource
because the server is unable to store the
representation needed to successfully complete the
request.  There is insufficient free space left in
your storage allocation.</p>
<p>Additionally, a 507 Insufficient Storage
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
```

I obtained the same results when running `nf-core sync` locally.

This also causes an nf-core lint error as the file "is not equal to the template"


### Command used and terminal output

```console
nf-core sync
```


### System information

I'm not sure what are the versions installed in the server.

Locally I was using `NXF_VER = 21.10.5` and nf-core tools `v2.2` on macOS
`create`: check HTML response is 200 when fetching logo
### Description of the bug

After an automated sync of the nf-core tools v2.2, the dark logo for Epitopeprediction was not created and instead this was inside that file:

```html 
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>507 Insufficient Storage</title>
</head><body>
<h1>Insufficient Storage</h1>
<p>The method could not be performed on the resource
because the server is unable to store the
representation needed to successfully complete the
request.  There is insufficient free space left in
your storage allocation.</p>
<p>Additionally, a 507 Insufficient Storage
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
```

I obtained the same results when running `nf-core sync` locally.

This also causes an nf-core lint error as the file "is not equal to the template"


### Command used and terminal output

```console
nf-core sync
```


### System information

I'm not sure what are the versions installed in the server.

Locally I was using `NXF_VER = 21.10.5` and nf-core tools `v2.2` on macOS

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nf_core/create.py`
Content:
```
1 #!/usr/bin/env python
2 """Creates a nf-core pipeline matching the current
3 organization's specification based on a template.
4 """
5 from genericpath import exists
6 import git
7 import jinja2
8 import logging
9 import os
10 import pathlib
11 import requests
12 import shutil
13 import sys
14 
15 import nf_core
16 
17 log = logging.getLogger(__name__)
18 
19 
20 class PipelineCreate(object):
21     """Creates a nf-core pipeline a la carte from the nf-core best-practice template.
22 
23     Args:
24         name (str): Name for the pipeline.
25         description (str): Description for the pipeline.
26         author (str): Authors name of the pipeline.
27         version (str): Version flag. Semantic versioning only. Defaults to `1.0dev`.
28         no_git (bool): Prevents the creation of a local Git repository for the pipeline. Defaults to False.
29         force (bool): Overwrites a given workflow directory with the same name. Defaults to False.
30             May the force be with you.
31         outdir (str): Path to the local output directory.
32     """
33 
34     def __init__(self, name, description, author, version="1.0dev", no_git=False, force=False, outdir=None):
35         self.short_name = name.lower().replace(r"/\s+/", "-").replace("nf-core/", "").replace("/", "-")
36         self.name = f"nf-core/{self.short_name}"
37         self.name_noslash = self.name.replace("/", "-")
38         self.name_docker = self.name.replace("nf-core", "nfcore")
39         self.description = description
40         self.author = author
41         self.version = version
42         self.no_git = no_git
43         self.force = force
44         self.outdir = outdir
45         if not self.outdir:
46             self.outdir = os.path.join(os.getcwd(), self.name_noslash)
47 
48     def init_pipeline(self):
49         """Creates the nf-core pipeline."""
50 
51         # Make the new pipeline
52         self.render_template()
53 
54         # Init the git repository and make the first commit
55         if not self.no_git:
56             self.git_init_pipeline()
57 
58         log.info(
59             "[green bold]!!!!!! IMPORTANT !!!!!!\n\n"
60             + "[green not bold]If you are interested in adding your pipeline to the nf-core community,\n"
61             + "PLEASE COME AND TALK TO US IN THE NF-CORE SLACK BEFORE WRITING ANY CODE!\n\n"
62             + "[default]Please read: [link=https://nf-co.re/developers/adding_pipelines#join-the-community]https://nf-co.re/developers/adding_pipelines#join-the-community[/link]"
63         )
64 
65     def render_template(self):
66         """Runs Jinja to create a new nf-core pipeline."""
67         log.info(f"Creating new nf-core pipeline: '{self.name}'")
68 
69         # Check if the output directory exists
70         if os.path.exists(self.outdir):
71             if self.force:
72                 log.warning(f"Output directory '{self.outdir}' exists - continuing as --force specified")
73             else:
74                 log.error(f"Output directory '{self.outdir}' exists!")
75                 log.info("Use -f / --force to overwrite existing files")
76                 sys.exit(1)
77         else:
78             os.makedirs(self.outdir)
79 
80         # Run jinja2 for each file in the template folder
81         env = jinja2.Environment(
82             loader=jinja2.PackageLoader("nf_core", "pipeline-template"), keep_trailing_newline=True
83         )
84         template_dir = os.path.join(os.path.dirname(__file__), "pipeline-template")
85         object_attrs = vars(self)
86         object_attrs["nf_core_version"] = nf_core.__version__
87 
88         # Can't use glob.glob() as need recursive hidden dotfiles - https://stackoverflow.com/a/58126417/713980
89         template_files = list(pathlib.Path(template_dir).glob("**/*"))
90         template_files += list(pathlib.Path(template_dir).glob("*"))
91         ignore_strs = [".pyc", "__pycache__", ".pyo", ".pyd", ".DS_Store", ".egg"]
92         rename_files = {
93             "workflows/pipeline.nf": f"workflows/{self.short_name}.nf",
94             "lib/WorkflowPipeline.groovy": f"lib/Workflow{self.short_name[0].upper()}{self.short_name[1:]}.groovy",
95         }
96 
97         for template_fn_path_obj in template_files:
98 
99             template_fn_path = str(template_fn_path_obj)
100             if os.path.isdir(template_fn_path):
101                 continue
102             if any([s in template_fn_path for s in ignore_strs]):
103                 log.debug(f"Ignoring '{template_fn_path}' in jinja2 template creation")
104                 continue
105 
106             # Set up vars and directories
107             template_fn = os.path.relpath(template_fn_path, template_dir)
108             output_path = os.path.join(self.outdir, template_fn)
109             if template_fn in rename_files:
110                 output_path = os.path.join(self.outdir, rename_files[template_fn])
111             os.makedirs(os.path.dirname(output_path), exist_ok=True)
112 
113             try:
114                 # Just copy binary files
115                 if nf_core.utils.is_file_binary(template_fn_path):
116                     raise AttributeError(f"Binary file: {template_fn_path}")
117 
118                 # Got this far - render the template
119                 log.debug(f"Rendering template file: '{template_fn}'")
120                 j_template = env.get_template(template_fn)
121                 rendered_output = j_template.render(object_attrs)
122 
123                 # Write to the pipeline output file
124                 with open(output_path, "w") as fh:
125                     log.debug(f"Writing to output file: '{output_path}'")
126                     fh.write(rendered_output)
127 
128             # Copy the file directly instead of using Jinja
129             except (AttributeError, UnicodeDecodeError) as e:
130                 log.debug(f"Copying file without Jinja: '{output_path}' - {e}")
131                 shutil.copy(template_fn_path, output_path)
132 
133             # Something else went wrong
134             except Exception as e:
135                 log.error(f"Copying raw file as error rendering with Jinja: '{output_path}' - {e}")
136                 shutil.copy(template_fn_path, output_path)
137 
138             # Mirror file permissions
139             template_stat = os.stat(template_fn_path)
140             os.chmod(output_path, template_stat.st_mode)
141 
142         # Make a logo and save it
143         self.make_pipeline_logo()
144 
145     def make_pipeline_logo(self):
146         """Fetch a logo for the new pipeline from the nf-core website"""
147 
148         logo_url = f"https://nf-co.re/logo/{self.short_name}?theme=light"
149         log.debug(f"Fetching logo from {logo_url}")
150 
151         email_logo_path = f"{self.outdir}/assets/{self.name_noslash}_logo_light.png"
152         os.makedirs(os.path.dirname(email_logo_path), exist_ok=True)
153         log.debug(f"Writing logo to '{email_logo_path}'")
154         r = requests.get(f"{logo_url}&w=400")
155         with open(email_logo_path, "wb") as fh:
156             fh.write(r.content)
157         for theme in ["dark", "light"]:
158             readme_logo_path = f"{self.outdir}/docs/images/{self.name_noslash}_logo_{theme}.png"
159             log.debug(f"Writing logo to '{readme_logo_path}'")
160             os.makedirs(os.path.dirname(readme_logo_path), exist_ok=True)
161             r = requests.get(f"{logo_url}?w=600&theme={theme}")
162             with open(readme_logo_path, "wb") as fh:
163                 fh.write(r.content)
164 
165     def git_init_pipeline(self):
166         """Initialises the new pipeline as a Git repository and submits first commit."""
167         log.info("Initialising pipeline git repository")
168         repo = git.Repo.init(self.outdir)
169         repo.git.add(A=True)
170         repo.index.commit(f"initial template build from nf-core/tools, version {nf_core.__version__}")
171         # Add TEMPLATE branch to git repository
172         repo.git.branch("TEMPLATE")
173         repo.git.branch("dev")
174         log.info(
175             "Done. Remember to add a remote and push to GitHub:\n"
176             f"[white on grey23] cd {self.outdir} \n"
177             " git remote add origin git@github.com:USERNAME/REPO_NAME.git \n"
178             " git push --all origin                                       "
179         )
180         log.info("This will also push your newly created dev branch and the TEMPLATE branch for syncing.")
181
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/nf_core/create.py b/nf_core/create.py
--- a/nf_core/create.py
+++ b/nf_core/create.py
@@ -4,13 +4,16 @@
 """
 from genericpath import exists
 import git
+import imghdr
 import jinja2
 import logging
 import os
 import pathlib
+import random
 import requests
 import shutil
 import sys
+import time
 
 import nf_core
 
@@ -149,18 +152,52 @@
         log.debug(f"Fetching logo from {logo_url}")
 
         email_logo_path = f"{self.outdir}/assets/{self.name_noslash}_logo_light.png"
-        os.makedirs(os.path.dirname(email_logo_path), exist_ok=True)
-        log.debug(f"Writing logo to '{email_logo_path}'")
-        r = requests.get(f"{logo_url}&w=400")
-        with open(email_logo_path, "wb") as fh:
-            fh.write(r.content)
+        self.download_pipeline_logo(f"{logo_url}&w=400", email_logo_path)
         for theme in ["dark", "light"]:
+            readme_logo_url = f"{logo_url}?w=600&theme={theme}"
             readme_logo_path = f"{self.outdir}/docs/images/{self.name_noslash}_logo_{theme}.png"
-            log.debug(f"Writing logo to '{readme_logo_path}'")
-            os.makedirs(os.path.dirname(readme_logo_path), exist_ok=True)
-            r = requests.get(f"{logo_url}?w=600&theme={theme}")
-            with open(readme_logo_path, "wb") as fh:
+            self.download_pipeline_logo(readme_logo_url, readme_logo_path)
+
+    def download_pipeline_logo(self, url, img_fn):
+        """Attempt to download a logo from the website. Retry if it fails."""
+        os.makedirs(os.path.dirname(img_fn), exist_ok=True)
+        attempt = 0
+        max_attempts = 10
+        retry_delay = 0  # x up to 10 each time, so first delay will be 1-100 seconds
+        while attempt < max_attempts:
+            # If retrying, wait a while
+            if retry_delay > 0:
+                log.info(f"Waiting {retry_delay} seconds before next image fetch attempt")
+                time.sleep(retry_delay)
+
+            attempt += 1
+            # Use a random number to avoid the template sync hitting the website simultaneously for all pipelines
+            retry_delay = random.randint(1, 100) * attempt
+            log.debug(f"Fetching logo '{img_fn}' (attempt {attempt})")
+            try:
+                # Try to fetch the logo from the website
+                r = requests.get(url, timeout=180)
+                if r.status_code != 200:
+                    raise UserWarning(f"Got status code {r.status_code}")
+                # Check that the returned image looks right
+
+            except (ConnectionError, UserWarning) as e:
+                # Something went wrong - try again
+                log.warning(e)
+                log.error(f"Connection error - retrying")
+                continue
+
+            # Write the new logo to the file
+            with open(img_fn, "wb") as fh:
                 fh.write(r.content)
+            # Check that the file looks valid
+            image_type = imghdr.what(img_fn)
+            if image_type != "png":
+                log.error(f"Logo from the website didn't look like an image: '{image_type}'")
+                continue
+
+            # Got this far, presumably it's good - break the retry loop
+            break
 
     def git_init_pipeline(self):
         """Initialises the new pipeline as a Git repository and submits first commit."""

{"golden_diff": "diff --git a/nf_core/create.py b/nf_core/create.py\n--- a/nf_core/create.py\n+++ b/nf_core/create.py\n@@ -4,13 +4,16 @@\n \"\"\"\n from genericpath import exists\n import git\n+import imghdr\n import jinja2\n import logging\n import os\n import pathlib\n+import random\n import requests\n import shutil\n import sys\n+import time\n \n import nf_core\n \n@@ -149,18 +152,52 @@\n         log.debug(f\"Fetching logo from {logo_url}\")\n \n         email_logo_path = f\"{self.outdir}/assets/{self.name_noslash}_logo_light.png\"\n-        os.makedirs(os.path.dirname(email_logo_path), exist_ok=True)\n-        log.debug(f\"Writing logo to '{email_logo_path}'\")\n-        r = requests.get(f\"{logo_url}&w=400\")\n-        with open(email_logo_path, \"wb\") as fh:\n-            fh.write(r.content)\n+        self.download_pipeline_logo(f\"{logo_url}&w=400\", email_logo_path)\n         for theme in [\"dark\", \"light\"]:\n+            readme_logo_url = f\"{logo_url}?w=600&theme={theme}\"\n             readme_logo_path = f\"{self.outdir}/docs/images/{self.name_noslash}_logo_{theme}.png\"\n-            log.debug(f\"Writing logo to '{readme_logo_path}'\")\n-            os.makedirs(os.path.dirname(readme_logo_path), exist_ok=True)\n-            r = requests.get(f\"{logo_url}?w=600&theme={theme}\")\n-            with open(readme_logo_path, \"wb\") as fh:\n+            self.download_pipeline_logo(readme_logo_url, readme_logo_path)\n+\n+    def download_pipeline_logo(self, url, img_fn):\n+        \"\"\"Attempt to download a logo from the website. Retry if it fails.\"\"\"\n+        os.makedirs(os.path.dirname(img_fn), exist_ok=True)\n+        attempt = 0\n+        max_attempts = 10\n+        retry_delay = 0  # x up to 10 each time, so first delay will be 1-100 seconds\n+        while attempt < max_attempts:\n+            # If retrying, wait a while\n+            if retry_delay > 0:\n+                log.info(f\"Waiting {retry_delay} seconds before next image fetch attempt\")\n+                time.sleep(retry_delay)\n+\n+            attempt += 1\n+            # Use a random number to avoid the template sync hitting the website simultaneously for all pipelines\n+            retry_delay = random.randint(1, 100) * attempt\n+            log.debug(f\"Fetching logo '{img_fn}' (attempt {attempt})\")\n+            try:\n+                # Try to fetch the logo from the website\n+                r = requests.get(url, timeout=180)\n+                if r.status_code != 200:\n+                    raise UserWarning(f\"Got status code {r.status_code}\")\n+                # Check that the returned image looks right\n+\n+            except (ConnectionError, UserWarning) as e:\n+                # Something went wrong - try again\n+                log.warning(e)\n+                log.error(f\"Connection error - retrying\")\n+                continue\n+\n+            # Write the new logo to the file\n+            with open(img_fn, \"wb\") as fh:\n                 fh.write(r.content)\n+            # Check that the file looks valid\n+            image_type = imghdr.what(img_fn)\n+            if image_type != \"png\":\n+                log.error(f\"Logo from the website didn't look like an image: '{image_type}'\")\n+                continue\n+\n+            # Got this far, presumably it's good - break the retry loop\n+            break\n \n     def git_init_pipeline(self):\n         \"\"\"Initialises the new pipeline as a Git repository and submits first commit.\"\"\"\n", "issue": "`create`: check HTML response is 200 when fetching logo\n### Description of the bug\r\n\r\nAfter an automated sync of the nf-core tools v2.2, the dark logo for Epitopeprediction was not created and instead this was inside that file:\r\n\r\n```html \r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html><head>\r\n<title>507 Insufficient Storage</title>\r\n</head><body>\r\n<h1>Insufficient Storage</h1>\r\n<p>The method could not be performed on the resource\r\nbecause the server is unable to store the\r\nrepresentation needed to successfully complete the\r\nrequest.  There is insufficient free space left in\r\nyour storage allocation.</p>\r\n<p>Additionally, a 507 Insufficient Storage\r\nerror was encountered while trying to use an ErrorDocument to handle the request.</p>\r\n</body></html>\r\n```\r\n\r\nI obtained the same results when running `nf-core sync` locally.\r\n\r\nThis also causes an nf-core lint error as the file \"is not equal to the template\"\r\n\r\n\r\n### Command used and terminal output\r\n\r\n```console\r\nnf-core sync\r\n```\r\n\r\n\r\n### System information\r\n\r\nI'm not sure what are the versions installed in the server.\r\n\r\nLocally I was using `NXF_VER = 21.10.5` and nf-core tools `v2.2` on macOS\n`create`: check HTML response is 200 when fetching logo\n### Description of the bug\r\n\r\nAfter an automated sync of the nf-core tools v2.2, the dark logo for Epitopeprediction was not created and instead this was inside that file:\r\n\r\n```html \r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html><head>\r\n<title>507 Insufficient Storage</title>\r\n</head><body>\r\n<h1>Insufficient Storage</h1>\r\n<p>The method could not be performed on the resource\r\nbecause the server is unable to store the\r\nrepresentation needed to successfully complete the\r\nrequest.  There is insufficient free space left in\r\nyour storage allocation.</p>\r\n<p>Additionally, a 507 Insufficient Storage\r\nerror was encountered while trying to use an ErrorDocument to handle the request.</p>\r\n</body></html>\r\n```\r\n\r\nI obtained the same results when running `nf-core sync` locally.\r\n\r\nThis also causes an nf-core lint error as the file \"is not equal to the template\"\r\n\r\n\r\n### Command used and terminal output\r\n\r\n```console\r\nnf-core sync\r\n```\r\n\r\n\r\n### System information\r\n\r\nI'm not sure what are the versions installed in the server.\r\n\r\nLocally I was using `NXF_VER = 21.10.5` and nf-core tools `v2.2` on macOS\n", "before_files": [{"content": "#!/usr/bin/env python\n\"\"\"Creates a nf-core pipeline matching the current\norganization's specification based on a template.\n\"\"\"\nfrom genericpath import exists\nimport git\nimport jinja2\nimport logging\nimport os\nimport pathlib\nimport requests\nimport shutil\nimport sys\n\nimport nf_core\n\nlog = logging.getLogger(__name__)\n\n\nclass PipelineCreate(object):\n    \"\"\"Creates a nf-core pipeline a la carte from the nf-core best-practice template.\n\n    Args:\n        name (str): Name for the pipeline.\n        description (str): Description for the pipeline.\n        author (str): Authors name of the pipeline.\n        version (str): Version flag. Semantic versioning only. Defaults to `1.0dev`.\n        no_git (bool): Prevents the creation of a local Git repository for the pipeline. Defaults to False.\n        force (bool): Overwrites a given workflow directory with the same name. Defaults to False.\n            May the force be with you.\n        outdir (str): Path to the local output directory.\n    \"\"\"\n\n    def __init__(self, name, description, author, version=\"1.0dev\", no_git=False, force=False, outdir=None):\n        self.short_name = name.lower().replace(r\"/\\s+/\", \"-\").replace(\"nf-core/\", \"\").replace(\"/\", \"-\")\n        self.name = f\"nf-core/{self.short_name}\"\n        self.name_noslash = self.name.replace(\"/\", \"-\")\n        self.name_docker = self.name.replace(\"nf-core\", \"nfcore\")\n        self.description = description\n        self.author = author\n        self.version = version\n        self.no_git = no_git\n        self.force = force\n        self.outdir = outdir\n        if not self.outdir:\n            self.outdir = os.path.join(os.getcwd(), self.name_noslash)\n\n    def init_pipeline(self):\n        \"\"\"Creates the nf-core pipeline.\"\"\"\n\n        # Make the new pipeline\n        self.render_template()\n\n        # Init the git repository and make the first commit\n        if not self.no_git:\n            self.git_init_pipeline()\n\n        log.info(\n            \"[green bold]!!!!!! IMPORTANT !!!!!!\\n\\n\"\n            + \"[green not bold]If you are interested in adding your pipeline to the nf-core community,\\n\"\n            + \"PLEASE COME AND TALK TO US IN THE NF-CORE SLACK BEFORE WRITING ANY CODE!\\n\\n\"\n            + \"[default]Please read: [link=https://nf-co.re/developers/adding_pipelines#join-the-community]https://nf-co.re/developers/adding_pipelines#join-the-community[/link]\"\n        )\n\n    def render_template(self):\n        \"\"\"Runs Jinja to create a new nf-core pipeline.\"\"\"\n        log.info(f\"Creating new nf-core pipeline: '{self.name}'\")\n\n        # Check if the output directory exists\n        if os.path.exists(self.outdir):\n            if self.force:\n                log.warning(f\"Output directory '{self.outdir}' exists - continuing as --force specified\")\n            else:\n                log.error(f\"Output directory '{self.outdir}' exists!\")\n                log.info(\"Use -f / --force to overwrite existing files\")\n                sys.exit(1)\n        else:\n            os.makedirs(self.outdir)\n\n        # Run jinja2 for each file in the template folder\n        env = jinja2.Environment(\n            loader=jinja2.PackageLoader(\"nf_core\", \"pipeline-template\"), keep_trailing_newline=True\n        )\n        template_dir = os.path.join(os.path.dirname(__file__), \"pipeline-template\")\n        object_attrs = vars(self)\n        object_attrs[\"nf_core_version\"] = nf_core.__version__\n\n        # Can't use glob.glob() as need recursive hidden dotfiles - https://stackoverflow.com/a/58126417/713980\n        template_files = list(pathlib.Path(template_dir).glob(\"**/*\"))\n        template_files += list(pathlib.Path(template_dir).glob(\"*\"))\n        ignore_strs = [\".pyc\", \"__pycache__\", \".pyo\", \".pyd\", \".DS_Store\", \".egg\"]\n        rename_files = {\n            \"workflows/pipeline.nf\": f\"workflows/{self.short_name}.nf\",\n            \"lib/WorkflowPipeline.groovy\": f\"lib/Workflow{self.short_name[0].upper()}{self.short_name[1:]}.groovy\",\n        }\n\n        for template_fn_path_obj in template_files:\n\n            template_fn_path = str(template_fn_path_obj)\n            if os.path.isdir(template_fn_path):\n                continue\n            if any([s in template_fn_path for s in ignore_strs]):\n                log.debug(f\"Ignoring '{template_fn_path}' in jinja2 template creation\")\n                continue\n\n            # Set up vars and directories\n            template_fn = os.path.relpath(template_fn_path, template_dir)\n            output_path = os.path.join(self.outdir, template_fn)\n            if template_fn in rename_files:\n                output_path = os.path.join(self.outdir, rename_files[template_fn])\n            os.makedirs(os.path.dirname(output_path), exist_ok=True)\n\n            try:\n                # Just copy binary files\n                if nf_core.utils.is_file_binary(template_fn_path):\n                    raise AttributeError(f\"Binary file: {template_fn_path}\")\n\n                # Got this far - render the template\n                log.debug(f\"Rendering template file: '{template_fn}'\")\n                j_template = env.get_template(template_fn)\n                rendered_output = j_template.render(object_attrs)\n\n                # Write to the pipeline output file\n                with open(output_path, \"w\") as fh:\n                    log.debug(f\"Writing to output file: '{output_path}'\")\n                    fh.write(rendered_output)\n\n            # Copy the file directly instead of using Jinja\n            except (AttributeError, UnicodeDecodeError) as e:\n                log.debug(f\"Copying file without Jinja: '{output_path}' - {e}\")\n                shutil.copy(template_fn_path, output_path)\n\n            # Something else went wrong\n            except Exception as e:\n                log.error(f\"Copying raw file as error rendering with Jinja: '{output_path}' - {e}\")\n                shutil.copy(template_fn_path, output_path)\n\n            # Mirror file permissions\n            template_stat = os.stat(template_fn_path)\n            os.chmod(output_path, template_stat.st_mode)\n\n        # Make a logo and save it\n        self.make_pipeline_logo()\n\n    def make_pipeline_logo(self):\n        \"\"\"Fetch a logo for the new pipeline from the nf-core website\"\"\"\n\n        logo_url = f\"https://nf-co.re/logo/{self.short_name}?theme=light\"\n        log.debug(f\"Fetching logo from {logo_url}\")\n\n        email_logo_path = f\"{self.outdir}/assets/{self.name_noslash}_logo_light.png\"\n        os.makedirs(os.path.dirname(email_logo_path), exist_ok=True)\n        log.debug(f\"Writing logo to '{email_logo_path}'\")\n        r = requests.get(f\"{logo_url}&w=400\")\n        with open(email_logo_path, \"wb\") as fh:\n            fh.write(r.content)\n        for theme in [\"dark\", \"light\"]:\n            readme_logo_path = f\"{self.outdir}/docs/images/{self.name_noslash}_logo_{theme}.png\"\n            log.debug(f\"Writing logo to '{readme_logo_path}'\")\n            os.makedirs(os.path.dirname(readme_logo_path), exist_ok=True)\n            r = requests.get(f\"{logo_url}?w=600&theme={theme}\")\n            with open(readme_logo_path, \"wb\") as fh:\n                fh.write(r.content)\n\n    def git_init_pipeline(self):\n        \"\"\"Initialises the new pipeline as a Git repository and submits first commit.\"\"\"\n        log.info(\"Initialising pipeline git repository\")\n        repo = git.Repo.init(self.outdir)\n        repo.git.add(A=True)\n        repo.index.commit(f\"initial template build from nf-core/tools, version {nf_core.__version__}\")\n        # Add TEMPLATE branch to git repository\n        repo.git.branch(\"TEMPLATE\")\n        repo.git.branch(\"dev\")\n        log.info(\n            \"Done. Remember to add a remote and push to GitHub:\\n\"\n            f\"[white on grey23] cd {self.outdir} \\n\"\n            \" git remote add origin git@github.com:USERNAME/REPO_NAME.git \\n\"\n            \" git push --all origin                                       \"\n        )\n        log.info(\"This will also push your newly created dev branch and the TEMPLATE branch for syncing.\")\n", "path": "nf_core/create.py"}], "after_files": [{"content": "#!/usr/bin/env python\n\"\"\"Creates a nf-core pipeline matching the current\norganization's specification based on a template.\n\"\"\"\nfrom genericpath import exists\nimport git\nimport imghdr\nimport jinja2\nimport logging\nimport os\nimport pathlib\nimport random\nimport requests\nimport shutil\nimport sys\nimport time\n\nimport nf_core\n\nlog = logging.getLogger(__name__)\n\n\nclass PipelineCreate(object):\n    \"\"\"Creates a nf-core pipeline a la carte from the nf-core best-practice template.\n\n    Args:\n        name (str): Name for the pipeline.\n        description (str): Description for the pipeline.\n        author (str): Authors name of the pipeline.\n        version (str): Version flag. Semantic versioning only. Defaults to `1.0dev`.\n        no_git (bool): Prevents the creation of a local Git repository for the pipeline. Defaults to False.\n        force (bool): Overwrites a given workflow directory with the same name. Defaults to False.\n            May the force be with you.\n        outdir (str): Path to the local output directory.\n    \"\"\"\n\n    def __init__(self, name, description, author, version=\"1.0dev\", no_git=False, force=False, outdir=None):\n        self.short_name = name.lower().replace(r\"/\\s+/\", \"-\").replace(\"nf-core/\", \"\").replace(\"/\", \"-\")\n        self.name = f\"nf-core/{self.short_name}\"\n        self.name_noslash = self.name.replace(\"/\", \"-\")\n        self.name_docker = self.name.replace(\"nf-core\", \"nfcore\")\n        self.description = description\n        self.author = author\n        self.version = version\n        self.no_git = no_git\n        self.force = force\n        self.outdir = outdir\n        if not self.outdir:\n            self.outdir = os.path.join(os.getcwd(), self.name_noslash)\n\n    def init_pipeline(self):\n        \"\"\"Creates the nf-core pipeline.\"\"\"\n\n        # Make the new pipeline\n        self.render_template()\n\n        # Init the git repository and make the first commit\n        if not self.no_git:\n            self.git_init_pipeline()\n\n        log.info(\n            \"[green bold]!!!!!! IMPORTANT !!!!!!\\n\\n\"\n            + \"[green not bold]If you are interested in adding your pipeline to the nf-core community,\\n\"\n            + \"PLEASE COME AND TALK TO US IN THE NF-CORE SLACK BEFORE WRITING ANY CODE!\\n\\n\"\n            + \"[default]Please read: [link=https://nf-co.re/developers/adding_pipelines#join-the-community]https://nf-co.re/developers/adding_pipelines#join-the-community[/link]\"\n        )\n\n    def render_template(self):\n        \"\"\"Runs Jinja to create a new nf-core pipeline.\"\"\"\n        log.info(f\"Creating new nf-core pipeline: '{self.name}'\")\n\n        # Check if the output directory exists\n        if os.path.exists(self.outdir):\n            if self.force:\n                log.warning(f\"Output directory '{self.outdir}' exists - continuing as --force specified\")\n            else:\n                log.error(f\"Output directory '{self.outdir}' exists!\")\n                log.info(\"Use -f / --force to overwrite existing files\")\n                sys.exit(1)\n        else:\n            os.makedirs(self.outdir)\n\n        # Run jinja2 for each file in the template folder\n        env = jinja2.Environment(\n            loader=jinja2.PackageLoader(\"nf_core\", \"pipeline-template\"), keep_trailing_newline=True\n        )\n        template_dir = os.path.join(os.path.dirname(__file__), \"pipeline-template\")\n        object_attrs = vars(self)\n        object_attrs[\"nf_core_version\"] = nf_core.__version__\n\n        # Can't use glob.glob() as need recursive hidden dotfiles - https://stackoverflow.com/a/58126417/713980\n        template_files = list(pathlib.Path(template_dir).glob(\"**/*\"))\n        template_files += list(pathlib.Path(template_dir).glob(\"*\"))\n        ignore_strs = [\".pyc\", \"__pycache__\", \".pyo\", \".pyd\", \".DS_Store\", \".egg\"]\n        rename_files = {\n            \"workflows/pipeline.nf\": f\"workflows/{self.short_name}.nf\",\n            \"lib/WorkflowPipeline.groovy\": f\"lib/Workflow{self.short_name[0].upper()}{self.short_name[1:]}.groovy\",\n        }\n\n        for template_fn_path_obj in template_files:\n\n            template_fn_path = str(template_fn_path_obj)\n            if os.path.isdir(template_fn_path):\n                continue\n            if any([s in template_fn_path for s in ignore_strs]):\n                log.debug(f\"Ignoring '{template_fn_path}' in jinja2 template creation\")\n                continue\n\n            # Set up vars and directories\n            template_fn = os.path.relpath(template_fn_path, template_dir)\n            output_path = os.path.join(self.outdir, template_fn)\n            if template_fn in rename_files:\n                output_path = os.path.join(self.outdir, rename_files[template_fn])\n            os.makedirs(os.path.dirname(output_path), exist_ok=True)\n\n            try:\n                # Just copy binary files\n                if nf_core.utils.is_file_binary(template_fn_path):\n                    raise AttributeError(f\"Binary file: {template_fn_path}\")\n\n                # Got this far - render the template\n                log.debug(f\"Rendering template file: '{template_fn}'\")\n                j_template = env.get_template(template_fn)\n                rendered_output = j_template.render(object_attrs)\n\n                # Write to the pipeline output file\n                with open(output_path, \"w\") as fh:\n                    log.debug(f\"Writing to output file: '{output_path}'\")\n                    fh.write(rendered_output)\n\n            # Copy the file directly instead of using Jinja\n            except (AttributeError, UnicodeDecodeError) as e:\n                log.debug(f\"Copying file without Jinja: '{output_path}' - {e}\")\n                shutil.copy(template_fn_path, output_path)\n\n            # Something else went wrong\n            except Exception as e:\n                log.error(f\"Copying raw file as error rendering with Jinja: '{output_path}' - {e}\")\n                shutil.copy(template_fn_path, output_path)\n\n            # Mirror file permissions\n            template_stat = os.stat(template_fn_path)\n            os.chmod(output_path, template_stat.st_mode)\n\n        # Make a logo and save it\n        self.make_pipeline_logo()\n\n    def make_pipeline_logo(self):\n        \"\"\"Fetch a logo for the new pipeline from the nf-core website\"\"\"\n\n        logo_url = f\"https://nf-co.re/logo/{self.short_name}?theme=light\"\n        log.debug(f\"Fetching logo from {logo_url}\")\n\n        email_logo_path = f\"{self.outdir}/assets/{self.name_noslash}_logo_light.png\"\n        self.download_pipeline_logo(f\"{logo_url}&w=400\", email_logo_path)\n        for theme in [\"dark\", \"light\"]:\n            readme_logo_url = f\"{logo_url}?w=600&theme={theme}\"\n            readme_logo_path = f\"{self.outdir}/docs/images/{self.name_noslash}_logo_{theme}.png\"\n            self.download_pipeline_logo(readme_logo_url, readme_logo_path)\n\n    def download_pipeline_logo(self, url, img_fn):\n        \"\"\"Attempt to download a logo from the website. Retry if it fails.\"\"\"\n        os.makedirs(os.path.dirname(img_fn), exist_ok=True)\n        attempt = 0\n        max_attempts = 10\n        retry_delay = 0  # x up to 10 each time, so first delay will be 1-100 seconds\n        while attempt < max_attempts:\n            # If retrying, wait a while\n            if retry_delay > 0:\n                log.info(f\"Waiting {retry_delay} seconds before next image fetch attempt\")\n                time.sleep(retry_delay)\n\n            attempt += 1\n            # Use a random number to avoid the template sync hitting the website simultaneously for all pipelines\n            retry_delay = random.randint(1, 100) * attempt\n            log.debug(f\"Fetching logo '{img_fn}' (attempt {attempt})\")\n            try:\n                # Try to fetch the logo from the website\n                r = requests.get(url, timeout=180)\n                if r.status_code != 200:\n                    raise UserWarning(f\"Got status code {r.status_code}\")\n                # Check that the returned image looks right\n\n            except (ConnectionError, UserWarning) as e:\n                # Something went wrong - try again\n                log.warning(e)\n                log.error(f\"Connection error - retrying\")\n                continue\n\n            # Write the new logo to the file\n            with open(img_fn, \"wb\") as fh:\n                fh.write(r.content)\n            # Check that the file looks valid\n            image_type = imghdr.what(img_fn)\n            if image_type != \"png\":\n                log.error(f\"Logo from the website didn't look like an image: '{image_type}'\")\n                continue\n\n            # Got this far, presumably it's good - break the retry loop\n            break\n\n    def git_init_pipeline(self):\n        \"\"\"Initialises the new pipeline as a Git repository and submits first commit.\"\"\"\n        log.info(\"Initialising pipeline git repository\")\n        repo = git.Repo.init(self.outdir)\n        repo.git.add(A=True)\n        repo.index.commit(f\"initial template build from nf-core/tools, version {nf_core.__version__}\")\n        # Add TEMPLATE branch to git repository\n        repo.git.branch(\"TEMPLATE\")\n        repo.git.branch(\"dev\")\n        log.info(\n            \"Done. Remember to add a remote and push to GitHub:\\n\"\n            f\"[white on grey23] cd {self.outdir} \\n\"\n            \" git remote add origin git@github.com:USERNAME/REPO_NAME.git \\n\"\n            \" git push --all origin                                       \"\n        )\n        log.info(\"This will also push your newly created dev branch and the TEMPLATE branch for syncing.\")\n", "path": "nf_core/create.py"}]}