From 672d68bd4a0b899855dbb880679c06f0656fbc65 Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Wed, 3 Jul 2024 11:26:06 -0700 Subject: [PATCH] git: Use merge-tree in patchsets Topic: mergetreepatch --- revup/git.py | 60 +++++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/revup/git.py b/revup/git.py index d2d4ca2..3bee9a2 100644 --- a/revup/git.py +++ b/revup/git.py @@ -614,19 +614,28 @@ async def get_diff_summary( async def merge_tree_commit( self, - branch1: GitCommitHash, - branch2: GitCommitHash, + tree1: GitCommitHash, + tree2: GitCommitHash, new_commit_info: CommitHeader, - merge_base: Optional[GitCommitHash] = None, + merge_base: GitCommitHash, + strategy: Optional[str] = None, ) -> GitCommitHash: """ Perform a combined git merge-tree and commit-tree, returning a git commit hash. Raises GitConflictException if there are conflicts while merging the trees. """ - args = ["merge-tree", "--write-tree", "--messages", "-z"] - if merge_base: - args.extend(["--merge-base", merge_base]) - args.extend([branch1, branch2]) + args = [ + "merge-tree", + "--write-tree", + "--messages", + "-z", + "--merge-base", + merge_base, + tree1, + tree2, + ] + if strategy is not None: + args.extend(["-X", strategy]) ret, stdout = await self.git(*args, raiseonerror=False) @@ -750,8 +759,7 @@ async def make_virtual_diff_target( """ Return a commit (optionally on top of parent) that provides a way to get the diff from old head to new head while accounting for the fact that new base might have been rebased since - old base. This new commit makes an effort to include only files that were actually changed, - while excluding files that were changed upstream as part of the rebase. + old base. We do this by resetting any files that changed in the old_base->old_head diff to their old_head versions in new_base. The returned tree will thus have the following properties @@ -769,38 +777,14 @@ async def make_virtual_diff_target( delete the file, but probably the least confusing of the alternatives of showing no diff and showing the old_head->old_base diff. """ - new_index: List[str] = [] - - # Transform diff-tree raw output to ls-files style output, taking only the new version - for m in RE_RAW_DIFF_TREE_LINE.finditer( - await self.git_stdout("diff-tree", "-r", "--no-commit-id", "--raw", old_base, old_head) - ): - new_index.append(f"{m.group('new_mode')} {m.group('new_hash')} 0\t{m.group('path')}") - - if not new_index: - # No files were actually changed, so no diff needs to be applied to new_base - return new_base - - temp_index_path = self.get_scratch_dir() + "/index.temp" - git_env = { - "GIT_INDEX_FILE": temp_index_path, - } - shutil.copy(f"{self.git_dir}/index", temp_index_path) - await self.git("reset", "-q", "--no-refresh", new_base, "--", ":/", env=git_env) - await self.git( - "update-index", - "--index-info", - input_str="\n".join(new_index), - env=git_env, - ) - - tree = GitTreeHash(await self.git_stdout("write-tree", env=git_env)) - new_commit_info = CommitHeader(tree, [parent] if parent else []) + new_commit_info = CommitHeader(GitTreeHash(""), [parent] if parent else []) new_commit_info.commit_msg = ( - f"revup virtual diff target\n\n{old_base}\n{old_head}\n{new_base}\n{new_head}" + f"revup virtual diff target\n\n{old_base}\n{old_head}\n{new_base}\n{new_head}\n\n" + "revup uses this branch internally to generate github viewable diffs. The commits and " + "diffs between commits are not meaningful or useful." ) - return await self.commit_tree(new_commit_info) + return await self.merge_tree_commit(old_head, new_base, new_commit_info, old_base, "ours") async def soft_reset(self, new_commit: GitCommitHash, env: Dict) -> None: await self.git("reset", "--soft", new_commit, env=env)