Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion revup/amend.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ async def rebuild_stack_last_touched(
amended.author_date = commit_obj.author_date
amended.committer_name = commit_obj.committer_name
amended.committer_email = commit_obj.committer_email
amended.committer_date = commit_obj.committer_date
# Refresh committer date, like git commit --amend.
amended.committer_date = ""
amended.commit_msg = commit_obj.commit_msg
new_commit = await git_ctx.commit_tree(amended)
else:
Expand Down Expand Up @@ -319,6 +320,9 @@ async def get_has_unstaged() -> bool:
if len(stack) == 0:
raise RevupUsageException(f"Couldn't find any commits between HEAD and {commit}~")

# Refresh the amended commit's committer date, like git commit --amend.
stack[0].committer_date = ""

if args.insert:
# Create a new empty commit after the given commit
stack[0].parents = [stack[0].commit_id]
Expand Down
10 changes: 8 additions & 2 deletions tests/git_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ async def write_file(self, name, content):
async def read_file(self, name):
return (self.tmp_dir / name).read_text()

async def commit(self, message, files=None):
async def commit(self, message, files=None, committer_date=None):
if files:
for name, content in files.items():
await self.write_file(name, content)
await self.git_ctx.git("add", name)
ts = self._next_timestamp()
env = {
"GIT_AUTHOR_DATE": ts,
"GIT_COMMITTER_DATE": ts,
"GIT_COMMITTER_DATE": committer_date if committer_date is not None else ts,
}
await self.git_ctx.git("commit", "-m", message, "--allow-empty", env=env)
self.commit_count += 1
Expand All @@ -121,6 +121,12 @@ async def get_commit_message(self, ref="HEAD"):
async def get_commit_hash(self, ref="HEAD"):
return GitCommitHash(await self.git_ctx.git_stdout("rev-parse", ref))

async def get_author_date(self, ref="HEAD"):
return await self.git_ctx.git_stdout("log", "-1", "--format=%at", ref)

async def get_committer_date(self, ref="HEAD"):
return await self.git_ctx.git_stdout("log", "-1", "--format=%ct", ref)

async def get_file_at_commit(self, name, ref="HEAD"):
return await self.git_ctx.git_stdout("show", f"{ref}:{name}")

Expand Down
55 changes: 55 additions & 0 deletions tests/test_amend.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,61 @@ async def test_amend_changes_commit_hashes(self):
assert new_head != orig_head


class TestAmendCommitterDate:
@async_test
async def test_amend_refreshes_committer_date_preserves_author(self):
async with GitTestEnvironment() as env:
await env.commit("root", {"root.txt": "r"})
# Epoch 0 so any refresh is strictly greater
await env.commit("first", {"a.txt": "a"}, committer_date="@0 +0000")
orig_author = await env.get_author_date()

await env.stage_file("a.txt", "modified")
args = make_amend_args(edit=False)
ret = await amend.main(args, env.git_ctx)

assert ret == 0
assert await env.get_author_date() == orig_author
assert int(await env.get_committer_date()) > 0

@async_test
async def test_amend_earlier_commit_refreshes_committer_date(self):
async with GitTestEnvironment() as env:
await env.commit("root", {"root.txt": "r"})
await env.commit("first", {"a.txt": "a"}, committer_date="@0 +0000")
await env.commit("second", {"b.txt": "b"})
orig_author = await env.get_author_date("HEAD~1")
top_committer = await env.get_committer_date("HEAD")

await env.stage_file("a.txt", "modified")
args = make_amend_args(ref_or_topic="HEAD~1", edit=False)
ret = await amend.main(args, env.git_ctx)

assert ret == 0
assert await env.get_author_date("HEAD~1") == orig_author
assert int(await env.get_committer_date("HEAD~1")) > 0
# Recreated commit keeps its date
assert await env.get_committer_date("HEAD") == top_committer

@async_test
async def test_last_touched_refreshes_committer_date(self):
async with GitTestEnvironment() as env:
await env.commit("root", {"root.txt": "r"})
await env.git_ctx.git("branch", "origin/main", "HEAD")
# Old but valid timestamp; the refresh must move committer date past it.
await env.commit(
"first\n\nTopic: alpha", {"a.txt": "v1"}, committer_date="@1000000000 +0000"
)
orig_author = await env.get_author_date("HEAD")

await env.stage_file("a.txt", "v2")
args = make_amend_args(last_touched=True, parse_topics=True)
await amend.main(args, env.git_ctx)

assert await env.get_author_date("HEAD") == orig_author
assert int(await env.get_committer_date("HEAD")) > 1000000000


class TestAmendSingleCommit:
@async_test
async def test_amend_only_commit_above_root(self):
Expand Down
Loading