Skip to content

Commit

Permalink
fix: properly support diffs over updates with new interactive answers
Browse files Browse the repository at this point in the history
Just like 802d0f9, but this time we make sure that interactive answers also work as expected.

Basically, I moved the creation of the updated and clean worker after the copying of the real destination worker. With this change, we can ask the user for answers and make sure we use them when producing the clean and updated copy.

@moduon MT-1075
  • Loading branch information
yajo committed Mar 31, 2023
1 parent b352841 commit 8987339
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 19 deletions.
29 changes: 14 additions & 15 deletions copier/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,12 +700,10 @@ def _apply_update(self):
)
subproject_subdir = self.subproject.local_abspath.relative_to(subproject_top)

# Copy old template into a temporary destination
with TemporaryDirectory(
prefix=f"{__name__}.update_diff."
) as old_copy, TemporaryDirectory(
prefix=f"{__name__}.recopy_diff."
) as new_copy:
prefix=f"{__name__}.old_copy."
) as old_copy, TemporaryDirectory(prefix=f"{__name__}.new_copy.") as new_copy:
# Copy old template into a temporary destination
old_worker = replace(
self,
dst_path=old_copy / subproject_subdir,
Expand All @@ -716,16 +714,6 @@ def _apply_update(self):
vcs_ref=self.subproject.template.commit,
)
old_worker.run_copy()
new_worker = replace(
self,
dst_path=new_copy / subproject_subdir,
data=replace(self, defaults=True).answers.combined,
defaults=True,
quiet=True,
src_path=self.subproject.template.url,
)
new_worker.run_copy()
compared = dircmp(old_copy, new_copy)
# Extract diff between temporary destination and real destination
with local.cwd(old_copy):
self._git_initialize_repo()
Expand All @@ -752,6 +740,17 @@ def _apply_update(self):
del self.subproject.last_answers
# Do a normal update in final destination
self.run_copy()
# Render with the same answers in an empty dir to avoid pollution
new_worker = replace(
self,
dst_path=new_copy / subproject_subdir,
data=self.answers.combined,
defaults=True,
quiet=True,
src_path=self.subproject.template.url,
)
new_worker.run_copy()
compared = dircmp(old_copy, new_copy)
# Try to apply cached diff into final destination
with local.cwd(subproject_top):
apply_cmd = git["apply", "--reject", "--exclude", self.answers_relpath]
Expand Down
35 changes: 31 additions & 4 deletions tests/test_updatediff.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from textwrap import dedent
from typing import Optional

import pexpect
import pytest
import yaml
from plumbum import local
Expand All @@ -14,7 +15,13 @@
from copier.main import run_copy, run_update
from copier.types import Literal

from .helpers import BRACKET_ENVOPS_JSON, SUFFIX_TMPL, build_file_tree
from .helpers import (
BRACKET_ENVOPS_JSON,
COPIER_PATH,
SUFFIX_TMPL,
Spawn,
build_file_tree,
)


@pytest.mark.impure
Expand Down Expand Up @@ -632,8 +639,9 @@ def test_file_removed(tmp_path_factory: pytest.TempPathFactory) -> None:
assert not (dst / "dir 5").exists()


@pytest.mark.parametrize("interactive", [True, False])
def test_update_inline_changed_answers_and_questions(
tmp_path_factory: pytest.TempPathFactory,
tmp_path_factory: pytest.TempPathFactory, interactive: bool, spawn: Spawn
) -> None:
src, dst = map(tmp_path_factory.mktemp, ("src", "dst"))
with local.cwd(src):
Expand Down Expand Up @@ -677,7 +685,14 @@ def test_update_inline_changed_answers_and_questions(
git("commit", "-am2")
git("tag", "2")
# Init project
run_copy(str(src), dst, data={"b": True}, vcs_ref="1")
if interactive:
tui = spawn(COPIER_PATH + ("-r1", "copy", str(src), str(dst)), timeout=10)
tui.expect_exact("b (bool)")
tui.expect_exact("(y/N)")
tui.send("y")
tui.expect_exact(pexpect.EOF)
else:
run_copy(str(src), dst, data={"b": True}, vcs_ref="1")
assert "ccc" not in (dst / "content").read_text()
with local.cwd(dst):
git("init")
Expand All @@ -696,7 +711,19 @@ def test_update_inline_changed_answers_and_questions(
)
git("commit", "-am2")
# Update from template, inline, with answer changes
run_update(data={"c": True}, defaults=True, overwrite=True, conflict="inline")
if interactive:
tui = spawn(COPIER_PATH + ("-w", "update", "--conflict=inline"), timeout=10)
tui.expect_exact("b (bool)")
tui.expect_exact("(Y/n)")
tui.sendline()
tui.expect_exact("c (bool)")
tui.expect_exact("(y/N)")
tui.send("y")
tui.expect_exact(pexpect.EOF)
else:
run_update(
data={"c": True}, defaults=True, overwrite=True, conflict="inline"
)
assert Path("content").read_text() == dedent(
"""\
aaa
Expand Down

0 comments on commit 8987339

Please sign in to comment.