fix(updating): ignore last answer of when: false questions

A recorded answer may exist when the question's `when` value gets switched from `when: true` to `when: false`, e.g. when the value is templated or changes across Copier template versions.
This commit is contained in:
Sigurd Spieckermann 2025-04-02 11:58:01 +02:00 committed by Sigurd Spieckermann
parent ef00375221
commit b078959972
3 changed files with 103 additions and 0 deletions

View File

@ -563,6 +563,10 @@ class Worker:
if not question.get_when():
# Omit its answer from the answers file.
self.answers.hide(var_name)
# Delete last answers to re-compute the answer from the default
# value (if it exists).
if var_name in self.answers.last:
del self.answers.last[var_name]
# Skip immediately to the next question when it has no default
# value.
if question.default is MISSING:

View File

@ -130,3 +130,50 @@ def test_recopy_dont_validate_computed_value(
run_recopy(dst, overwrite=True)
answers = load_answersfile_data(dst)
assert "computed" not in answers
def test_conditional_computed_value(tmp_path_factory: pytest.TempPathFactory) -> None:
src, dst = map(tmp_path_factory.mktemp, ("src", "dst"))
build_file_tree(
{
src / "copier.yml": (
"""\
first:
type: bool
second:
type: bool
default: "{{ first }}"
when: "{{ first }}"
"""
),
src / "{{ _copier_conf.answers_file }}.jinja": (
"{{ _copier_answers|to_nice_yaml }}"
),
src / "log.txt.jinja": "{{ first }} {{ second }}",
}
)
git_save(src)
run_copy(str(src), dst, data={"first": True}, defaults=True)
answers = load_answersfile_data(dst)
assert answers["first"] is True
assert answers["second"] is True
assert (dst / "log.txt").read_text() == "True True"
git_save(dst, "v1")
run_recopy(dst, data={"first": False}, overwrite=True)
answers = load_answersfile_data(dst)
assert answers["first"] is False
assert "second" not in answers
assert (dst / "log.txt").read_text() == "False False"
git_save(dst, "v2")
run_recopy(dst, data={"first": True}, defaults=True, overwrite=True)
answers = load_answersfile_data(dst)
assert answers["first"] is True
assert answers["second"] is True
assert (dst / "log.txt").read_text() == "True True"

View File

@ -1869,3 +1869,55 @@ def test_conflict_on_update_with_unicode_in_content(
zzz🐍
"""
)
def test_conditional_computed_value(tmp_path_factory: pytest.TempPathFactory) -> None:
src, dst = map(tmp_path_factory.mktemp, ("src", "dst"))
build_file_tree(
{
src / "copier.yml": (
"""\
first:
type: bool
second:
type: bool
default: "{{ first }}"
when: "{{ first }}"
"""
),
src / "{{ _copier_conf.answers_file }}.jinja": (
"{{ _copier_answers|to_nice_yaml }}"
),
src / "log.txt.jinja": "{{ first }} {{ second }}",
}
)
with local.cwd(src):
git_init("v1")
git("tag", "v1")
run_copy(str(src), dst, data={"first": True}, defaults=True)
answers = load_answersfile_data(dst)
assert answers["first"] is True
assert answers["second"] is True
assert (dst / "log.txt").read_text() == "True True"
with local.cwd(dst):
git_init("v1")
run_update(dst, data={"first": False}, overwrite=True)
answers = load_answersfile_data(dst)
assert answers["first"] is False
assert "second" not in answers
assert (dst / "log.txt").read_text() == "False False"
with local.cwd(dst):
git("add", ".")
git("commit", "-m", "v2")
run_update(dst, data={"first": True}, defaults=True, overwrite=True)
answers = load_answersfile_data(dst)
assert answers["first"] is True
assert answers["second"] is True
assert (dst / "log.txt").read_text() == "True True"