Skip to content

fix: resolve local template paths to absolute before storing in answers file - #2717

Open
Oscar-SR wants to merge 6 commits into
copier-org:masterfrom
Oscar-SR:fix/resolve-local-template-path
Open

fix: resolve local template paths to absolute before storing in answers file#2717
Oscar-SR wants to merge 6 commits into
copier-org:masterfrom
Oscar-SR:fix/resolve-local-template-path

Conversation

@Oscar-SR

@Oscar-SR Oscar-SR commented Jun 8, 2026

Copy link
Copy Markdown

This fix resolves local template paths to absolute before storing them in the answers file, so they remain valid regardless of the CWD when running copier update.

Remote URLs (gh:, https://, git@) are unaffected since they don't resolve to local paths.

Fixes #335

@sisp

sisp commented Jun 8, 2026

Copy link
Copy Markdown
Member

I think this change would break the use case described in #2589. One can always provide an absolute path to copier copy to record an absolute path in .copier-answers.yml. Always converting to an absolute path seems like convenience for your use case at the cost of (likely) breaking some (admittedly rare but known) other use cases.

Comment thread copier/_main.py Outdated
@Oscar-SR
Oscar-SR requested a review from lhupfeldt June 9, 2026 06:12

@lhupfeldt lhupfeldt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be test cases.

Note that I'm not a maintainer.

Comment thread copier/_main.py Outdated
Comment thread copier/_main.py Outdated

@sisp sisp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking, this is a breaking change because a template path relative to the subproject may break moving the project directory to a different location. But it might be a valuable change to be included in the next major release.

Comment thread copier/_main.py Outdated
@Oscar-SR

Copy link
Copy Markdown
Author

Thanks for the feedback! I have refactored the code using pathlib, removed the self.template.url validation and added the missing test cases. Let me know if everything looks good now.

@Oscar-SR
Oscar-SR requested a review from sisp June 14, 2026 10:45
@sisp

sisp commented Jun 19, 2026

Copy link
Copy Markdown
Member

With the current implementation, relative paths including .. are not computed, so the conversion of an absolute path to a relative path is limited to a template path within the project root, which is quite an edge case. I'm not sure I see the value in the current implementation because you can navigate to the project root and run copier copy with a relative path to the local template directory. And updating a project with copier update currently only works when the current working directory is the project root which may not be intuitive if your current working directory was different when running copier copy. The only potential enhancement I can imagine is recording the relative path to a local template converted to the path relative to the project root when Copier internally changes the working directory to the project root on copier update, so you can run copier update path/to/project no matter the current working directory.

@sisp

sisp commented Jun 19, 2026

Copy link
Copy Markdown
Member

Re-reading #335 (comment) again, I think converting a local template path that is relative to the current working directory to a path that is relative to the project root is strictly better:

  1. copier update works regardless of the current working directory.
  2. Moving the local template or project root independently invalidates the recorded relative template path in both cases, so there's no degradation.

For this to be useful, path traversal (involving ..) must be supported. pathlib.Path.relative_to(other, walk_up=True) would work, but walk_up was added in Python 3.12 while Copier supports Python 3.10+. This means, we'll need to use os.path.relpath until Copier drops support for Python 3.11 presumably after October 31, 2027.

There might be a way to make this change non-breaking: I think we could look up a local template according to the new relative path (relative to the project root) and fall back to looking it up according to the old relative path (relative to the current working directory). In both cases, the new relative path would be recorded in the updated answers file on copier update. This way, existing projects are automatically migrated to the new path. We would deprecate support for the old relative path and remove the fallback logic in the next major release (or perhaps after a sufficiently long period).

WDYT?

@lhupfeldt

lhupfeldt commented Jun 19, 2026

Copy link
Copy Markdown

Does the existing relative path work?
Let's say you run copier copy mytemplate mysubproject which would store mytemplate as the path.
Then you cd into mysubproject and run update, but now the stored path is wrong.

@sisp

sisp commented Jun 19, 2026

Copy link
Copy Markdown
Member

Do you mean with the changes of this PR or with the state of master?

With my suggestion, the template path in .copier-answers.yml would be ../mytemplate because that's the path relative to mysubproject.

@lhupfeldt

lhupfeldt commented Jun 19, 2026

Copy link
Copy Markdown

Do you mean with the changes of this PR or with the state of master?

I meant master.
I mean, is there any scenario currently working which would necessitate backwards compatibility?
I have no problem with our cd'ing hack breaking if this is implemented.

@sisp

sisp commented Jun 19, 2026

Copy link
Copy Markdown
Member

Hmmm, I think you're right. Currently, copier update with a recorded relative template path only works when executed in the same working directory as copier copy before. This still works when the relative template path is relative to the project root. Hence, no breaking change. 💡 But we still need the fallback to the current template path resolution.

Comment thread copier/_main.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shouldn't _src_path be stored as absolute path?

3 participants