mirror of
https://github.com/copier-org/copier.git
synced 2025-05-07 16:32:57 +00:00
214 lines
6.9 KiB
Markdown
214 lines
6.9 KiB
Markdown
# Frequently Asked Questions
|
|
|
|
## Can Copier be applied over a preexisting project?
|
|
|
|
Yes, of course. Copier understands this use case out of the box. That's actually what
|
|
powers features such as [updating](updating.md) or the ability of [applying multiple
|
|
templates to the same subproject][applying-multiple-templates-to-the-same-subproject].
|
|
|
|
!!! example
|
|
|
|
```shell
|
|
copier copy https://github.com/me/my-template.git ./my-preexisting-git-project
|
|
```
|
|
|
|
## How to use Copier from Docker or Podman?
|
|
|
|
Copier doesn't provide an image by default. However, it does provide a nix package, so
|
|
you can use Nix to run Copier reproducibly from within a container:
|
|
|
|
```shell
|
|
# Change for docker if needed
|
|
engine=podman
|
|
|
|
# You can pin the version; example: github:copier-org/copier/v8.0.0
|
|
copier=github:copier-org/copier
|
|
|
|
$engine container run --rm -it docker.io/nixos/nix \
|
|
nix --extra-experimental-features 'nix-command flakes' --accept-flake-config \
|
|
run $copier -- --help
|
|
```
|
|
|
|
You can even generate a reproducible minimal docker image with just Copier inside, with:
|
|
|
|
```shell
|
|
nix bundle --bundler github:NixOS/bundlers#toDockerImage \
|
|
github:copier-org/copier#packages.x86_64-linux.default
|
|
docker load < python*copier*.tar.gz
|
|
```
|
|
|
|
## How to create computed values?
|
|
|
|
Combine `default` and `when: false`.
|
|
|
|
!!! example
|
|
|
|
```yaml title="copier.yaml"
|
|
copyright_year:
|
|
type: int
|
|
default: 2024
|
|
|
|
next_year:
|
|
type: int
|
|
default: "{{ copyright_year + 1 }}" # This computes the value
|
|
when: false # This makes sure it isn't asked nor stored
|
|
```
|
|
|
|
See [advanced prompt formatting docs][advanced-prompt-formatting]. If you need more
|
|
power, see [below][how-can-i-alter-the-context-before-rendering-the-project].
|
|
|
|
## How can I alter the context before rendering the project?
|
|
|
|
**Use the [`ContextHook` extension][context-hook].** It lets you modify the context used
|
|
to render templates, so that you can add, change or remove variables. Since it is a
|
|
Python extension, you have the full power of Python at your fingertips, at the cost of
|
|
having to mark the template as [unsafe][].
|
|
|
|
[context-hook]:
|
|
https://github.com/copier-org/copier-templates-extensions#context-hook-extension
|
|
|
|
In order for Copier to be able to load and use the extension when generating a project,
|
|
it must be installed alongside Copier itself. More details in the [`jinja_extensions`
|
|
docs][jinja_extensions].
|
|
|
|
You can then configure your Jinja extensions in Copier's configuration file:
|
|
|
|
```yaml title="copier.yaml"
|
|
_jinja_extensions:
|
|
- copier_templates_extensions.TemplateExtensionLoader
|
|
- extensions/context.py:ContextUpdater
|
|
```
|
|
|
|
Following this example, you are supposed to provide a `context.py` file in the
|
|
`extensions` folder at the root of your template to modify the context. If for example
|
|
your `copier.yaml` contains a multiple-choice variable like this:
|
|
|
|
```yaml title="copier.yaml"
|
|
flavor:
|
|
type: str
|
|
choices:
|
|
- docker
|
|
- instances
|
|
- kubernetes
|
|
- none
|
|
```
|
|
|
|
The `context.py` file contains your context hook which could look like:
|
|
|
|
```python title="extensions/context.py"
|
|
from copier_templates_extensions import ContextHook
|
|
|
|
|
|
class ContextUpdater(ContextHook):
|
|
def hook(self, context):
|
|
flavor = context["flavor"] # user's answer to the "flavor" question
|
|
return {
|
|
"isDocker": flavor == "docker",
|
|
"isK8s": flavor == "kubernetes",
|
|
"isInstances": flavor == "instances",
|
|
"isLite": flavor == "none",
|
|
"isNotDocker": flavor != "docker",
|
|
"isNotK8s": flavor != "kubernetes",
|
|
"isNotInstances": flavor != "instances",
|
|
"isNotLite": flavor != "none",
|
|
"hasContainers": flavor in {"docker", "kubernetes"},
|
|
}
|
|
```
|
|
|
|
Before rendering each templated file/folder, the context will be updated with this new
|
|
context object that you return from the hook. If you wish to update the context in-place
|
|
rather than update it, set the `update` class attribute to false:
|
|
|
|
```python title="extensions/context.py"
|
|
from copier_templates_extensions import ContextHook
|
|
|
|
|
|
class ContextUpdater(ContextHook):
|
|
update = False
|
|
|
|
def hook(self, context):
|
|
flavor = context["flavor"] # user's answer to the "flavor" question
|
|
|
|
context["isDocker"] = flavor == "docker"
|
|
context["isK8s"] = flavor == "kubernetes"
|
|
context["isInstances"] = flavor == "instances"
|
|
context["isLite"] = flavor == "none"
|
|
|
|
context["isNotDocker"] = flavor != "docker"
|
|
context["isNotK8s"] = flavor != "kubernetes"
|
|
context["isNotInstances"] = flavor != "instances"
|
|
context["isNotLite"] = flavor != "none"
|
|
|
|
context["hasContainers"] = context["isDocker"] or context["isK8s"]
|
|
|
|
# you can now actually remove items from the context
|
|
del context["flavor"]
|
|
```
|
|
|
|
Now you can use these added variables in your Jinja templates, and in files and folders
|
|
names!
|
|
|
|
## Why Copier consumes a lot of resources?
|
|
|
|
If the repository containing the template is a shallow clone, the git process called by
|
|
Copier might consume unusually high resources. To avoid that, use a fully-cloned
|
|
repository.
|
|
|
|
## While developing, why the template doesn't include dirty changes?
|
|
|
|
Copier follows [a specific algorithm][templates-versions] to choose what reference to
|
|
use from the template. It also [includes dirty changes in the `HEAD` ref while
|
|
developing locally][copying-dirty-changes].
|
|
|
|
However, did you make sure you are selecting the `HEAD` ref for copying?
|
|
|
|
Imagine this is the status of your dirty template in `./src`:
|
|
|
|
```shell
|
|
$ git -C ./src status --porcelain=v1
|
|
?? new-file.txt
|
|
|
|
$ git -C ./src tag
|
|
v1.0.0
|
|
v2.0.0
|
|
```
|
|
|
|
Now, if you copy that template into a folder like this:
|
|
|
|
```shell
|
|
$ copier copy ./src ./dst
|
|
```
|
|
|
|
... you'll notice there's no `new-file.txt`. Why?
|
|
|
|
Well, Copier indeed included that into the `HEAD` ref. However, it still selected
|
|
`v2.0.0` as the ref to copy, because that's what Copier does.
|
|
|
|
However, if you do this:
|
|
|
|
```shell
|
|
$ copier copy -r HEAD ./src ./dst
|
|
```
|
|
|
|
... then you'll notice `new-file.txt` does exist. You passed a specific ref to copy, so
|
|
Copier skips its autodetection and just goes for the `HEAD` you already chose.
|
|
|
|
## How to pass credentials to Git?
|
|
|
|
If you do something like this, and the template supports updates, you'll notice that the
|
|
credentials will end up stored in [the answers file][file][the-copier-answersyml-file]:
|
|
|
|
```shell
|
|
copier copy https://myuser:example.com/repo.git .
|
|
```
|
|
|
|
To avoid that, the simplest fix is to clone using SSH with cryptographic key
|
|
authentication. If you cannot do that, then check out these links for strategies on
|
|
passing HTTPS credentials to Git:
|
|
|
|
- https://github.com/copier-org/copier/issues/466#issuecomment-2338160284
|
|
- https://stackoverflow.com/q/35942754
|
|
- https://git-scm.com/docs/gitcredentials
|
|
- https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage#_credential_caching
|
|
- https://github.com/topics/git-credential-helper
|