From patchwork Fri Apr 7 07:24:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13204526 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A230CC77B6F for ; Fri, 7 Apr 2023 07:25:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239851AbjDGHZb (ORCPT ); Fri, 7 Apr 2023 03:25:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56204 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239802AbjDGHZT (ORCPT ); Fri, 7 Apr 2023 03:25:19 -0400 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 806DFA5EC for ; Fri, 7 Apr 2023 00:24:59 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id v1so41606211wrv.1 for ; Fri, 07 Apr 2023 00:24:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680852290; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=xuVI6Uc5QrlddcahOUKqI+AWxo4BoHUhtAZC++P0hqo=; b=IMHk5mcDIq+IMJ0G4+u1gdtEVubYDVABL/Zw8pTOPo2wbi8vmFwqj6GI/2BvztfFdr Tpwhq2RmTLz04VmZySlgvQxabEMAz6XfzkLblX44IOlT2LT5wasYvThEcfLdmdNhNy3b llcRlNLXqzNx/RGFHV/k+XhBkw4VsVRs+t7Nn8v5NElHxH2urt0y7g7fwmpODGIBtSOR NYrf2uYnUh9ATc8MELp3OVv4y6EFeRu+zcOwToJ/r8eg8PjUPolsjxCN0RLTH3vcXXbB 2sK5IMXmGQyhf1qqirc5wvrlHmi7sEEd7Ku+SEV57IJtvgfBFCUl0hqrQQH1Db7kaV7Z qaJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680852290; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xuVI6Uc5QrlddcahOUKqI+AWxo4BoHUhtAZC++P0hqo=; b=v3ZQk1TFRMngCQ1hSeDaLkOqYDtkhm6Ls34BDbHL79i6d9cvtB4ULEHf06DyNcIzVP EB3nn24HTx3KyHP+rRudXysSVShr4+t6bBZW1FZ99hcCr4ljsTdwdFGTU1tltuHenqPN JKJLoq0BSoocgDf8x+JXMmOa1gbGt7GNoXnheSwqObnWKA2y9zDAa4zvnZsg0NxjKqq7 4qUKaaXPkqXOBWmM0yauTbKlXBkg2rSK6s5lmOjLRab48CIE7hkSzv0qqkkq5fCRHJmT 9MGJVjdifJ00MyO3dQRBY2qfwQJJtiRDmdodEDobNiCVGS8nHthv0Nzgx2dakvvx/dTm U5Bg== X-Gm-Message-State: AAQBX9fcbp6jTU5imn8MwwEXua307b/K9nhiSMi7u0WN9VUlFXnxXAA5 RF9msWCT2KfFm2WK1H1q2Ptrs23ZJ4qQxw== X-Google-Smtp-Source: AKy350YgiV2wWMf1dBnpA10Ef/UsUVcRd5wDY1803ryoOeeIYPfCP0++JT3CGgWLH9xWMcFPUwOoRQ== X-Received: by 2002:adf:dbc4:0:b0:2ce:ae5b:27a2 with SMTP id e4-20020adfdbc4000000b002ceae5b27a2mr555673wrj.17.1680852289940; Fri, 07 Apr 2023 00:24:49 -0700 (PDT) Received: from christian-Precision-5550.lan ([2001:861:3f04:7ca0:90e:3fb7:fec2:981]) by smtp.gmail.com with ESMTPSA id f7-20020a5d6647000000b002da1261aa44sm3782761wrw.48.2023.04.07.00.24.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 00:24:49 -0700 (PDT) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Christian Couder Subject: [PATCH 10/14] replay: make it a minimal server side command Date: Fri, 7 Apr 2023 09:24:11 +0200 Message-Id: <20230407072415.1360068-11-christian.couder@gmail.com> X-Mailer: git-send-email 2.40.0.228.gb2eb5bb98e In-Reply-To: <20230407072415.1360068-1-christian.couder@gmail.com> References: <20230407072415.1360068-1-christian.couder@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren We want this command to be a minimal command that just does server side picking of commits, displaying the results on stdout for higher level scripts to consume. So let's simplify it: * remove the worktree and index reading/writing, * remove the ref (and reflog) updating, * remove the assumptions tying us to HEAD, since (a) this is not a rebase and (b) we want to be able to pick commits in a bare repo, i.e. to/from branches that are not checked out and not the main branch, * remove unneeded includes, * handle rebasing multiple branches by printing on stdout the update ref commands that should be performed. The output can be piped into `git update-ref --stdin` for the ref updates to happen. In the future to make it easier for users to use this command directly maybe an option can be added to automatically pipe its output into `git update-ref`. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 86 ++++++++---------------- t/t6429-merge-sequence-rename-caching.sh | 32 ++++++--- 2 files changed, 52 insertions(+), 66 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index 9c795c05a7..119cfecfe7 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -6,17 +6,13 @@ #include "git-compat-util.h" #include "builtin.h" -#include "cache-tree.h" -#include "commit.h" #include "hex.h" #include "lockfile.h" #include "merge-ort.h" #include "parse-options.h" #include "refs.h" #include "revision.h" -#include "sequencer.h" #include "strvec.h" -#include "tree.h" static const char *short_commit_name(struct commit *commit) { @@ -93,6 +89,7 @@ static struct commit *pick_regular_commit(struct commit *pickme, pickme_tree = get_commit_tree(pickme); base_tree = get_commit_tree(base); + merge_opt->branch1 = short_commit_name(last_commit); merge_opt->branch2 = short_commit_name(pickme); merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2); @@ -113,15 +110,12 @@ int cmd_replay(int argc, const char **argv, const char *prefix) { struct commit *onto; const char *onto_name = NULL; - struct commit *last_commit = NULL, *last_picked_commit = NULL; - struct lock_file lock = LOCK_INIT; + struct commit *last_commit = NULL; struct strvec rev_walk_args = STRVEC_INIT; struct rev_info revs; struct commit *commit; struct merge_options merge_opt; - struct tree *head_tree; struct merge_result result; - struct strbuf reflog_msg = STRBUF_INIT; struct strbuf branch_name = STRBUF_INIT; int ret = 0; @@ -177,20 +171,19 @@ int cmd_replay(int argc, const char **argv, const char *prefix) init_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; - merge_opt.branch1 = "HEAD"; - head_tree = get_commit_tree(onto); - result.tree = head_tree; + result.tree = get_commit_tree(onto); last_commit = onto; while ((commit = get_revision(&revs))) { - struct commit *pick; + const struct name_decoration *decoration; if (!commit->parents) die(_("replaying down to root commit is not supported yet!")); if (commit->parents->next) die(_("replaying merge commits is not supported yet!")); - pick = pick_regular_commit(commit, last_commit, &merge_opt, &result); - if (!pick) { + last_commit = pick_regular_commit(commit, last_commit, &merge_opt, &result); + + if (!last_commit) { /* TODO: handle conflicts in sparse worktree instead */ struct object_id head; struct tree *head_tree; @@ -215,54 +208,31 @@ int cmd_replay(int argc, const char **argv, const char *prefix) oid_to_hex(&commit->object.oid)); } - last_commit = pick; - last_picked_commit = commit; - } - - repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR); - if (repo_read_index(the_repository) < 0) - BUG("Could not read index"); - - merge_switch_to_result(&merge_opt, head_tree, &result, 1, !result.clean); - - if (result.clean < 0) - exit(128); - - if (result.clean) { - strbuf_addf(&reflog_msg, "finish rebase %s onto %s", - oid_to_hex(&last_picked_commit->object.oid), - oid_to_hex(&last_commit->object.oid)); - if (update_ref(reflog_msg.buf, branch_name.buf, - &last_commit->object.oid, - &last_picked_commit->object.oid, - REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[2]); - die("Failed to update %s", argv[2]); - } - if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) - die(_("unable to update HEAD")); - - prime_cache_tree(the_repository, the_repository->index, - result.tree); - } else { - strbuf_addf(&reflog_msg, "rebase progress up to %s", - oid_to_hex(&last_picked_commit->object.oid)); - if (update_ref(reflog_msg.buf, "HEAD", - &last_commit->object.oid, - &onto->object.oid, - REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[2]); - die("Failed to update %s", argv[2]); + decoration = get_name_decoration(&commit->object); + if (!decoration) + continue; + + while (decoration) { + if (decoration->type == DECORATION_REF_LOCAL) { + printf("update %s %s %s\n", + decoration->name, + oid_to_hex(&last_commit->object.oid), + oid_to_hex(&commit->object.oid)); + } + decoration = decoration->next; } } - if (write_locked_index(&the_index, &lock, - COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die(_("unable to write %s"), get_index_file()); - ret = (result.clean == 0); + /* Cleanup */ + merge_finalize(&merge_opt, &result); + ret = result.clean; + cleanup: - strbuf_release(&reflog_msg); strbuf_release(&branch_name); release_revisions(&revs); - return ret; + + /* Return */ + if (ret < 0) + exit(128); + return ret ? 0 : 1; } diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index 40505c9054..bfdf7f30b3 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -71,7 +71,9 @@ test_expect_success 'caching renames does not preclude finding new ones' ' git switch upstream && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin tracked-files && test_line_count = 2 tracked-files && @@ -139,7 +141,9 @@ test_expect_success 'cherry-pick both a commit and its immediate revert' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 1 calls @@ -197,7 +201,9 @@ test_expect_success 'rename same file identically, then reintroduce it' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin tracked && test_line_count = 2 tracked && @@ -273,7 +279,9 @@ test_expect_success 'rename same file identically, then add file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin tracked && test_line_count = 4 tracked && @@ -450,7 +458,9 @@ test_expect_success 'dir rename unneeded, then add new file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 2 calls && @@ -515,7 +525,9 @@ test_expect_success 'dir rename unneeded, then rename existing file into old dir GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 3 calls && @@ -616,7 +628,9 @@ test_expect_success 'caching renames only on upstream side, part 1' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 1 calls && @@ -673,7 +687,9 @@ test_expect_success 'caching renames only on upstream side, part 2' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 2 calls &&