From patchwork Tue Jun 7 20:42:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872631 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 9BA28C43334 for ; Wed, 8 Jun 2022 00:33:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1386567AbiFHA35 (ORCPT ); Tue, 7 Jun 2022 20:29:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1839413AbiFHADJ (ORCPT ); Tue, 7 Jun 2022 20:03:09 -0400 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 44A7D1EEB93 for ; Tue, 7 Jun 2022 13:42:54 -0700 (PDT) Received: by mail-wr1-x430.google.com with SMTP id k16so25702147wrg.7 for ; Tue, 07 Jun 2022 13:42:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=C3VeTaSpsyjNjv445FZ5ATeKLyQuS87OAVtCJM+JQzE=; b=cBskUPcVirFGxYRKecOty/qShfOx32Z88XIOyLzOXQSDSgD4q7AzoLXSSqMqlevkAX LyzhwQ6tqpublcv/KtDSIPvJH9BAe0jRaUPLI24pQbX1M7CK1OezN0FKkdWtrZU25HlP AEIMcvXwhNCTe9VKoMXEupPshJoCa9i+/5mYX4/baIbEEa3etL95nUibwF6lC0gecdXc I9CzKrT8fmQlXo/IpuhwyMg0eLuMvyxKBZxmFGWTLEuLGLHohQOOvT6dd5Y1I34B6Jm1 9lHVy/OBw74YtR4tS2R5Mr0+tLEfrma53ZWZHKkXMlAD5J91JFVj3FVFYIyRW17r4XpB DttQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=C3VeTaSpsyjNjv445FZ5ATeKLyQuS87OAVtCJM+JQzE=; b=RUCdzdPwzBlTqghU4OfzQCpD8WrN5lqXTP19OvA22GXRDfPgPKifRaNdbeof+SgsDb cJ2JAFlCAXhr9Gx+zDpDsP+qK1vIRKfXLgE/9LI9lTy9CFiyJrbLk814rTkxE+hWHA/J LO4myouDZaU6AIOJYaXSFloCdYGAKbq2GTVaUN1MMmMS4l1p6ZFZLiwnlqY/rLoDXx/a +eiflZ74+z8AycPUmRmKXT5vsNf1hjjD2WCZeRKxGaDzNd+45EjSukW9J0UYmAkooT4q 0r8tdQrrwHPKIoYVDYjQo5QBPYQiUrXZgY0zZ+bEumzzjZk5ojmkoO/0RjWpyGDM37Tf Bf/g== X-Gm-Message-State: AOAM530V4DkRNJZ+GTWpmkLkaWxPBiG67dL0ySAkZ3tCoqUGG5o2Mc57 xr27Sv1cojd87hQ1OGs6bQBHei9nATUF9PnL X-Google-Smtp-Source: ABdhPJzRvknDl00rrsQKSPjonq6iUjfuTIcrGZGKWygcKQIWhuEIHNXRvB1Ol1WNQFCQRxP1E0sujA== X-Received: by 2002:a5d:570c:0:b0:210:32e1:7250 with SMTP id a12-20020a5d570c000000b0021032e17250mr30368720wrv.368.1654634572517; Tue, 07 Jun 2022 13:42:52 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e29-20020a5d595d000000b00213b93cff5fsm14641587wri.98.2022.06.07.13.42.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:51 -0700 (PDT) Message-Id: <4f9f34876413927d819313a70fcdefcad5b35689.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:43 +0000 Subject: [PATCH v2 1/7] log-tree: create for_each_decoration() Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee It can be helpful to iterate through all the decorations on a commit without necessarily writing them to a stream. Implement for_each_decoration() and reimplement format_decorations_extended() to use that iterator. Signed-off-by: Derrick Stolee --- log-tree.c | 111 ++++++++++++++++++++++++++++++++++++----------------- log-tree.h | 4 ++ 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/log-tree.c b/log-tree.c index d0ac0a6327a..b15a7c9db22 100644 --- a/log-tree.c +++ b/log-tree.c @@ -282,6 +282,54 @@ static void show_name(struct strbuf *sb, const struct name_decoration *decoratio strbuf_addstr(sb, decoration->name); } +struct format_decorations_context { + struct strbuf *sb; + int use_color; + const char *prefix; + const char *separator; + const char *suffix; + const char *color_commit; + const char *color_reset; + const struct name_decoration *current_and_HEAD; +}; + +static int append_decoration(const struct name_decoration *d, + void *data) +{ + struct format_decorations_context *ctx = data; + /* + * When both current and HEAD are there, only + * show HEAD->current where HEAD would have + * appeared, skipping the entry for current. + */ + if (d != ctx->current_and_HEAD) { + strbuf_addstr(ctx->sb, ctx->color_commit); + strbuf_addstr(ctx->sb, ctx->prefix); + strbuf_addstr(ctx->sb, ctx->color_reset); + strbuf_addstr(ctx->sb, decorate_get_color(ctx->use_color, d->type)); + if (d->type == DECORATION_REF_TAG) + strbuf_addstr(ctx->sb, "tag: "); + + show_name(ctx->sb, d); + + if (ctx->current_and_HEAD && + d->type == DECORATION_REF_HEAD) { + strbuf_addstr(ctx->sb, " -> "); + strbuf_addstr(ctx->sb, ctx->color_reset); + strbuf_addstr(ctx->sb, + decorate_get_color( + ctx->use_color, + ctx->current_and_HEAD->type)); + show_name(ctx->sb, ctx->current_and_HEAD); + } + strbuf_addstr(ctx->sb, ctx->color_reset); + + ctx->prefix = ctx->separator; + } + + return 0; +} + /* * The caller makes sure there is no funny color before calling. * format_decorations_extended makes sure the same after return. @@ -294,49 +342,42 @@ void format_decorations_extended(struct strbuf *sb, const char *suffix) { const struct name_decoration *decoration; - const struct name_decoration *current_and_HEAD; - const char *color_commit = - diff_get_color(use_color, DIFF_COMMIT); - const char *color_reset = - decorate_get_color(use_color, DECORATION_NONE); + struct format_decorations_context ctx = { + .sb = sb, + .use_color = use_color, + .prefix = prefix, + .separator = separator, + .suffix = suffix, + .color_commit = diff_get_color(use_color, DIFF_COMMIT), + .color_reset = decorate_get_color(use_color, DECORATION_NONE), + }; decoration = get_name_decoration(&commit->object); if (!decoration) return; - current_and_HEAD = current_pointed_by_HEAD(decoration); - while (decoration) { - /* - * When both current and HEAD are there, only - * show HEAD->current where HEAD would have - * appeared, skipping the entry for current. - */ - if (decoration != current_and_HEAD) { - strbuf_addstr(sb, color_commit); - strbuf_addstr(sb, prefix); - strbuf_addstr(sb, color_reset); - strbuf_addstr(sb, decorate_get_color(use_color, decoration->type)); - if (decoration->type == DECORATION_REF_TAG) - strbuf_addstr(sb, "tag: "); - - show_name(sb, decoration); - - if (current_and_HEAD && - decoration->type == DECORATION_REF_HEAD) { - strbuf_addstr(sb, " -> "); - strbuf_addstr(sb, color_reset); - strbuf_addstr(sb, decorate_get_color(use_color, current_and_HEAD->type)); - show_name(sb, current_and_HEAD); - } - strbuf_addstr(sb, color_reset); + ctx.current_and_HEAD = current_pointed_by_HEAD(decoration); - prefix = separator; - } + for_each_decoration(commit, append_decoration, &ctx); + + strbuf_addstr(sb, ctx.color_commit); + strbuf_addstr(sb, ctx.suffix); + strbuf_addstr(sb, ctx.color_reset); +} + +int for_each_decoration(const struct commit *c, decoration_fn fn, void *data) +{ + const struct name_decoration *decoration; + + decoration = get_name_decoration(&c->object); + while (decoration) { + int res; + if ((res = fn(decoration, data))) + return res; decoration = decoration->next; } - strbuf_addstr(sb, color_commit); - strbuf_addstr(sb, suffix); - strbuf_addstr(sb, color_reset); + + return 0; } void show_decorations(struct rev_info *opt, struct commit *commit) diff --git a/log-tree.h b/log-tree.h index e7e4641cf83..ea07da2625b 100644 --- a/log-tree.h +++ b/log-tree.h @@ -35,4 +35,8 @@ void fmt_output_commit(struct strbuf *, struct commit *, struct rev_info *); void fmt_output_subject(struct strbuf *, const char *subject, struct rev_info *); void fmt_output_email_subject(struct strbuf *, struct rev_info *); +typedef int decoration_fn(const struct name_decoration *d, + void *data); +int for_each_decoration(const struct commit *c, decoration_fn fn, void *data); + #endif From patchwork Tue Jun 7 20:42:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872711 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 53FA3C433EF for ; Wed, 8 Jun 2022 01:20:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347820AbiFHBUi (ORCPT ); Tue, 7 Jun 2022 21:20:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1443900AbiFHBBC (ORCPT ); Tue, 7 Jun 2022 21:01:02 -0400 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FD451EEBA0 for ; Tue, 7 Jun 2022 13:42:55 -0700 (PDT) Received: by mail-wm1-x329.google.com with SMTP id o37-20020a05600c512500b0039c4ba4c64dso4333994wms.2 for ; Tue, 07 Jun 2022 13:42:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=GZXWE3ow9ADaKIj0DAE4htB4Ma746HVMJhy/AKVLrMg=; b=YrYSKjhh7hE2nbU0QmFWgb62Q/XfUU9v1aVXY5i1g6H4GlsZ2DlA+WcDrFmWKlb9D/ XOUf3J6zN8ZX1MvoGm1WSYA9Qh3aUco4o3r9ndRvh+74WXI/o0kbBxWKT3aahahT1ty6 Wbp6/FgW4CGEpD3tTr73uf9B6/IxdrjvZ+CcqnkgDgblQljhFgDuSRaOuXpWPyl8BR7Y yquA93i2qPgXNLnYvDsFDQHB5cBdiyYmPpdqQp7Y6q0MSlUnnFBNNWkJ6i2giym3CCKM jjJKCh9dt5ddRqFH4OFeokLVhePUuHN8/uRTPv3zNAloOQNZ4hny+Z40nFhDes2iACWe 0TvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=GZXWE3ow9ADaKIj0DAE4htB4Ma746HVMJhy/AKVLrMg=; b=nORoYJdnGEGgIsfstpPIB+q6PNDJjKX8Ybgi0CUGJsaXZROf2WPUJerpeIVQcYO1hn 88ORDJbg34eT4PDp8bURRdW+I5PV321Z0joUoPNUw6JOT9/avAgGyy4UdFoP0p3WsPfh n/U5b09dPWOn1Ol5SuLwo9e9KOCU1tGsDD9gdhrlHTj62QIegd8sLoAmpMO8jb8cWCnQ Aj6RNRMu+KY8Jz5W3BXVBpaLSi/czB8DSyP1NSeKdagA1DYZTmnLiQ6CVek2/wWLv/Ol 5OCl/6zVbeWHm8Glh5EBEOtvB3BI552D9yNejwf9EWMLsYWbVWq6HwQ954560KmK5v9Z cvlQ== X-Gm-Message-State: AOAM5307wHanq7aKMJsYowoUnYr9wk460+85+6lyODAEEe19JTnmYG2x Xu/lSkRFB1z2lMXrgMB/JQAsxHXPjqTCP9+c X-Google-Smtp-Source: ABdhPJx8PKhhItJj/KVDkdzfZXVSE7pA0/BxRJWQlMZuKGv9u1AIxWTmEAnILGjADrlzeSVK3dhEbw== X-Received: by 2002:a05:600c:4e94:b0:397:62ab:f88f with SMTP id f20-20020a05600c4e9400b0039762abf88fmr59818247wmq.63.1654634573744; Tue, 07 Jun 2022 13:42:53 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id o12-20020a5d58cc000000b0020c6b78eb5asm19257060wrf.68.2022.06.07.13.42.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:53 -0700 (PDT) Message-Id: <5f54766e1032ebf3a331516a6dd696b997bdfdd8.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:44 +0000 Subject: [PATCH v2 2/7] branch: add branch_checked_out() helper Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The validate_new_branchname() method contains a check to see if a branch is checked out in any non-bare worktree. This is intended to prevent a force push that will mess up an existing checkout. This helper is not suitable to performing just that check, because the method will die() when the branch is checked out instead of returning an error code. Extract branch_checked_out() and use it within validate_new_branchname(). Another caller will be added in a coming change. Signed-off-by: Derrick Stolee --- branch.c | 24 ++++++++++++++++-------- branch.h | 8 ++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/branch.c b/branch.c index 2d6569b0c62..2e6419cdfa5 100644 --- a/branch.c +++ b/branch.c @@ -369,6 +369,19 @@ int validate_branchname(const char *name, struct strbuf *ref) return ref_exists(ref->buf); } +int branch_checked_out(const char *refname, char **path) +{ + struct worktree **worktrees = get_worktrees(); + const struct worktree *wt = find_shared_symref(worktrees, "HEAD", refname); + int result = wt && !wt->is_bare; + + if (result && path) + *path = xstrdup(wt->path); + + free_worktrees(worktrees); + return result; +} + /* * Check if a branch 'name' can be created as a new branch; die otherwise. * 'force' can be used when it is OK for the named branch already exists. @@ -377,9 +390,7 @@ int validate_branchname(const char *name, struct strbuf *ref) */ int validate_new_branchname(const char *name, struct strbuf *ref, int force) { - struct worktree **worktrees; - const struct worktree *wt; - + char *path; if (!validate_branchname(name, ref)) return 0; @@ -387,13 +398,10 @@ int validate_new_branchname(const char *name, struct strbuf *ref, int force) die(_("a branch named '%s' already exists"), ref->buf + strlen("refs/heads/")); - worktrees = get_worktrees(); - wt = find_shared_symref(worktrees, "HEAD", ref->buf); - if (wt && !wt->is_bare) + if (branch_checked_out(ref->buf, &path)) die(_("cannot force update the branch '%s' " "checked out at '%s'"), - ref->buf + strlen("refs/heads/"), wt->path); - free_worktrees(worktrees); + ref->buf + strlen("refs/heads/"), path); return 1; } diff --git a/branch.h b/branch.h index 560b6b96a8f..5ea93d217b1 100644 --- a/branch.h +++ b/branch.h @@ -101,6 +101,14 @@ void create_branches_recursively(struct repository *r, const char *name, const char *tracking_name, int force, int reflog, int quiet, enum branch_track track, int dry_run); + +/* + * Returns true if the branch at 'refname' is checked out at any + * non-bare worktree. The path of the worktree is stored in the + * given 'path', if provided. + */ +int branch_checked_out(const char *refname, char **path); + /* * Check if 'name' can be a valid name for a branch; die otherwise. * Return 1 if the named branch already exists; return 0 otherwise. From patchwork Tue Jun 7 20:42:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872710 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 4B05DC43334 for ; Wed, 8 Jun 2022 01:20:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345378AbiFHBUX (ORCPT ); Tue, 7 Jun 2022 21:20:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48724 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1443864AbiFHBAz (ORCPT ); Tue, 7 Jun 2022 21:00:55 -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 9B8551EEBAA for ; Tue, 7 Jun 2022 13:42:56 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id q15so17658673wrc.11 for ; Tue, 07 Jun 2022 13:42:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=ornPLfJhC7fIaVmbe59l55vjgSVTJqD+sQ62T0bkfsU=; b=bFNc794x958AVgpWzyCMdkxRO5doFj2Mgb6r+9P7JL4TNqnBzNLU9tcdwxl2GLW6u8 4eTQ0Gvb6YwBONwPym8ySwTX7ADeGuZYfk58TLPStRq9QlDCgmg9TfNo+6JMf9IAhO+b dBoZS1ueDBT6+gNa0eGIle6m5b/Cwz/I7jn0XAGaXTXoVqEkZqW6+bJvJ+e5Tpa3BHlJ F1/Zz3bnHOWvPHGlb/XYCsIHGugm/3qmJmOaWV/j44c93aVeH3//2tUtf8xd0mZ2GKVo K/LI9kLPjdpOatUK6CJ3KqUd0Y3I50ooci3qjgaqXl8bMIghNsFrdrhv0L3iTGyJbCjk dvgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=ornPLfJhC7fIaVmbe59l55vjgSVTJqD+sQ62T0bkfsU=; b=j/tS2GAmGoYZbmBkHUvJdmH2jJvmm44tuWuwOvCmaZVv5Yu9McJfGj37w99SnLhu/K 0yI4EtVSRN0ZqcD/oJMbIer51mbpKlQZ04mqTP0j7PQm1Jsicj1WZgJAhu1P5lb45Nwf UJ/A9YvRomhfQ5TupdFHgGkGLJcm7PTi/FA0SFSja8f/18zxXI6PYnf9l/hqQ/Bk+Ayh N/gjU9aWXA05KDH6xVqvzPdvGWDTKE3JqEg47++hCpV0sYwPDsmo3u/OGekmW7aDCxrC E/QUT8w+IRQJARMHh7pUjekLKzWELsZzWG2PxD3ogYsDVNLXitbClZr1USjnKMuB40YC qZFg== X-Gm-Message-State: AOAM530iZZYkLzQWDm39DH05pdErfb7QtUT22fgZfaPaqH/zB9RQAz3s cxlcDzT9dBAmDdnhsjZrfV/wsxef6OY9ITjg X-Google-Smtp-Source: ABdhPJyhnAFv7OShKXSI+50HPuvVVcvZOGl/8fLGIRzY510Lj41Rv/AyDlnuEPZ4+UW9VJqpbjqm0Q== X-Received: by 2002:adf:f646:0:b0:210:32ea:e679 with SMTP id x6-20020adff646000000b0021032eae679mr28514975wrp.395.1654634574876; Tue, 07 Jun 2022 13:42:54 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k7-20020a7bc407000000b00397402ae674sm3254567wmi.11.2022.06.07.13.42.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:54 -0700 (PDT) Message-Id: <9f261c7df2c0a433c6acc46ffefd8d2633fdc3d4.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:45 +0000 Subject: [PATCH v2 3/7] sequencer: define array with enum values Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The todo_command_info array defines which strings match with which todo_command enum values. The array is defined in the same order as the enum values, but if one changed without the other, then we would have unexpected results. Make it easier to see changes to the enum and this array by using the enum values as the indices of the array. Signed-off-by: Derrick Stolee --- sequencer.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sequencer.c b/sequencer.c index 8c3ed3532ac..8e26c9a6261 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1685,20 +1685,20 @@ static struct { char c; const char *str; } todo_command_info[] = { - { 'p', "pick" }, - { 0, "revert" }, - { 'e', "edit" }, - { 'r', "reword" }, - { 'f', "fixup" }, - { 's', "squash" }, - { 'x', "exec" }, - { 'b', "break" }, - { 'l', "label" }, - { 't', "reset" }, - { 'm', "merge" }, - { 0, "noop" }, - { 'd', "drop" }, - { 0, NULL } + [TODO_PICK] = { 'p', "pick" }, + [TODO_REVERT] = { 0, "revert" }, + [TODO_EDIT] = { 'e', "edit" }, + [TODO_REWORD] = { 'r', "reword" }, + [TODO_FIXUP] = { 'f', "fixup" }, + [TODO_SQUASH] = { 's', "squash" }, + [TODO_EXEC] = { 'x', "exec" }, + [TODO_BREAK] = { 'b', "break" }, + [TODO_LABEL] = { 'l', "label" }, + [TODO_RESET] = { 't', "reset" }, + [TODO_MERGE] = { 'm', "merge" }, + [TODO_NOOP] = { 0, "noop" }, + [TODO_DROP] = { 'd', "drop" }, + [TODO_COMMENT] = { 0, NULL }, }; static const char *command_to_string(const enum todo_command command) From patchwork Tue Jun 7 20:42:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872740 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 EF460C43334 for ; Wed, 8 Jun 2022 02:16:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229833AbiFHCQA (ORCPT ); Tue, 7 Jun 2022 22:16:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1445757AbiFHCNL (ORCPT ); Tue, 7 Jun 2022 22:13:11 -0400 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5DFE1EEBB2 for ; Tue, 7 Jun 2022 13:42:57 -0700 (PDT) Received: by mail-wm1-x330.google.com with SMTP id h62-20020a1c2141000000b0039aa4d054e2so12345805wmh.1 for ; Tue, 07 Jun 2022 13:42:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=OL+BpklyPzYC8RRzM08ZZr7cjA/4yf1+N5iD1T17F74=; b=IV00le046o7iuhYIlrAL5W16wA5muBD1X1UTJjGX7TFvqnsa+Xcs7GOX/23sd+tPR2 Ig7TC2xwuHIywMc0Bwb15YaJ0T/ZWcihrTB4zi1je/qChZ2slNSPHBvG23UMcw1ISIdp pOs6daCNjUykpwhQ4ANGnMoezL/uKAfruqFIiWaKGht1Hev8KBmt/lsoa9wKCPEimr6K KeSJZJm4Gb+zbpyaTzsStzuDHBV8PtJJuVADp4e9Xd+l1FnyDc8JGLMdqXygd8RyTn1r 3sunlncLukOGKaOyTwM4S+9bwXcv9b2sTKCt2hZayar3Tz5q1ej1QznlXSxi34NEQiJj NfQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=OL+BpklyPzYC8RRzM08ZZr7cjA/4yf1+N5iD1T17F74=; b=ZGJQF/Rg3rLtK8as5jgF7+AAcaLRD4lIGab/1L0ne6f6lGK39lKYf7/by0YfIVIRKq FUqaOBgLmz5tRqC1H514jNbRDDeafLstSrFcOiDOZWhppVbvwqX6OhkvhEtCaadq8LWt 9yEFdjZyASu9L6JlrW0QKFSq1R9gcTGO4MzQA/SUvyWf1+Uq9r0BJCbCxWqY1lTMKrMv ScP/SM82XtYuMClsqZCC1oDnkLkiqKRafacJCHBmpQfPX01vZ89OWdJPIqSOUOQgUHUP 01ky1ySGaUQrFyAbPxv3J4O+ffxsAgtr/dixt3bAOcDAEKRyrk3sydLOy7y/amP3h861 NDWw== X-Gm-Message-State: AOAM532DqKYxsNs4SelQsgY7qaGqfjYlt/nZoMOI1RZ2mZrgl0M7D6CL 7dnHltfReYQSzp65/mdLzRkagRFb1BUJ0TK2 X-Google-Smtp-Source: ABdhPJxEC383Z+dU2OutySDsJ8WP5WVD01/FyYZv7DScfwl8o22zpcMW+P+wL2pokSdCsB6z6z9rrA== X-Received: by 2002:a05:600c:6020:b0:39c:5cec:da86 with SMTP id az32-20020a05600c602000b0039c5cecda86mr3596449wmb.75.1654634575942; Tue, 07 Jun 2022 13:42:55 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id p19-20020a05600c1d9300b003942a244f39sm660272wms.18.2022.06.07.13.42.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:55 -0700 (PDT) Message-Id: <842b2186d250aca367e9680105d4d15f8cbb098e.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:46 +0000 Subject: [PATCH v2 4/7] sequencer: add update-refs command Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee Add the boilerplat for an "update-refs" command in the sequencer. This connects to the current no-op do_update_refs() which will be filled in after more connections are created. Signed-off-by: Derrick Stolee --- sequencer.c | 13 ++++++++++++- sequencer.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sequencer.c b/sequencer.c index 8e26c9a6261..68f7c76e896 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1696,6 +1696,7 @@ static struct { [TODO_LABEL] = { 'l', "label" }, [TODO_RESET] = { 't', "reset" }, [TODO_MERGE] = { 'm', "merge" }, + [TODO_UPDATE_REFS] = { 'u', "update-refs" }, [TODO_NOOP] = { 0, "noop" }, [TODO_DROP] = { 'd', "drop" }, [TODO_COMMENT] = { 0, NULL }, @@ -2442,7 +2443,9 @@ static int parse_insn_line(struct repository *r, struct todo_item *item, padding = strspn(bol, " \t"); bol += padding; - if (item->command == TODO_NOOP || item->command == TODO_BREAK) { + if (item->command == TODO_NOOP || + item->command == TODO_BREAK || + item->command == TODO_UPDATE_REFS) { if (bol != eol) return error(_("%s does not accept arguments: '%s'"), command_to_string(item->command), bol); @@ -4056,6 +4059,11 @@ leave_merge: return ret; } +static int do_update_refs(struct repository *r) +{ + return 0; +} + static int is_final_fixup(struct todo_list *todo_list) { int i = todo_list->current; @@ -4431,6 +4439,9 @@ static int pick_commits(struct repository *r, return error_with_patch(r, item->commit, arg, item->arg_len, opts, res, 0); + } else if (item->command == TODO_UPDATE_REFS) { + if ((res = do_update_refs(r))) + reschedule = 1; } else if (!is_noop(item->command)) return error(_("unknown command %d"), item->command); diff --git a/sequencer.h b/sequencer.h index da64473636b..c2b4e148d8f 100644 --- a/sequencer.h +++ b/sequencer.h @@ -95,6 +95,7 @@ enum todo_command { TODO_LABEL, TODO_RESET, TODO_MERGE, + TODO_UPDATE_REFS, /* commands that do nothing but are counted for reporting progress */ TODO_NOOP, TODO_DROP, From patchwork Tue Jun 7 20:42:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872753 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 C1C6DC433EF for ; Wed, 8 Jun 2022 02:47:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1387533AbiFHCq4 (ORCPT ); Tue, 7 Jun 2022 22:46:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1383619AbiFHCiT (ORCPT ); Tue, 7 Jun 2022 22:38:19 -0400 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DAC0F1EEBBA for ; Tue, 7 Jun 2022 13:42:58 -0700 (PDT) Received: by mail-wr1-x430.google.com with SMTP id h5so25745110wrb.0 for ; Tue, 07 Jun 2022 13:42:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=xQtPiRemFUH34jQg/iGfDV4TUzbqgs2eXYzQ8sn60ro=; b=mnX7L8pzp8BuviM7Lkn48l8zGSy4w8dIvP26Ngk0miIusyfkMuYdDKC4RqTCmp58+q qMf2SoDJx4ptVhO1v6Xmw6IPXztcZNR3bJun7306GQhXZm3maoNxI8ZYqH3HB/2bYtt7 el+edaaB5G9z9JKw8xafyRkClZT1pK8X9/2UMIzlCeRfLWrZwNcQdqP6W5VWLgZpNSN0 uPFzjNzuKvnJssaZg/AdSlunak4cOVUhQ6qV1t7IeLwwVjzRyuX0y8KYlb2/04FuRU4W XjY5kNgjazSASc/JRzJvIP5xvcvOhliKJkFxl5QKxltYwCbzW2WerQBu1Vse8Cs4aQzy /WWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=xQtPiRemFUH34jQg/iGfDV4TUzbqgs2eXYzQ8sn60ro=; b=uDCt/QFs969hUBu3lnLL33/P0rj5s/8voCobJ+HgLjvcZ9us+xTfQJHKSWlWj8x1v/ j/bajZImIUh9QxU6xrykyrojekFZXf7VbR+QB6a980sOxe7Yqh3KI0XK+DDCmC1CaXDF pkrQCmAhRW6dwBbi9PRVCAvkHTAEeVIAf7HotqULVq3RkL5b/wK2aJ7wp426YfaA4V2F MYE39oc0k/NAwJM31mtrRhyfmNEAamtXUaaVvb7tM+TxYF8SO0YNuhvpJSpBLz5twcjE Z76DKDZoTwLq2kJys0xDHYQ2Ee2ChVAXJTCuBAbhlw8BWtajBnpktTEbnTd2GKTSYvVm StYg== X-Gm-Message-State: AOAM530qY6W1MFrYUfIKEs/+BHLMKCpO4NDlzDq5Wr9h12G/KxkBoWXr o7XUSSEAOnAeDPSMvj0A3N1FbWcWJp47yqiL X-Google-Smtp-Source: ABdhPJw8tys9v27z5piuh/96ZKeoxLQj59QmORyc5YsSLLNxGnW94gbMhCrfy0ouwy0Y8bnaYSUCcA== X-Received: by 2002:a5d:5581:0:b0:20f:fc51:7754 with SMTP id i1-20020a5d5581000000b0020ffc517754mr29317918wrv.413.1654634577008; Tue, 07 Jun 2022 13:42:57 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n13-20020a5d400d000000b0020ff7246934sm18932052wrp.95.2022.06.07.13.42.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:56 -0700 (PDT) Message-Id: <0a4c110127b7628d3bc5b04534a4ea67fe46ef80.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:47 +0000 Subject: [PATCH v2 5/7] rebase: add --update-refs option Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee When working on a large feature, it can be helpful to break that feature into multiple smaller parts that become reviewed in sequence. During development or during review, a change to one part of the feature could affect multiple of these parts. An interactive rebase can help adjust the multi-part "story" of the branch. However, if there are branches tracking the different parts of the feature, then rebasing the entire list of commits can create commits not reachable from those "sub branches". It can take a manual step to update those branches. Add a new --update-refs option to 'git rebase -i' that adds 'label for-update-refs/*' steps to the todo file whenever a commit that is being rebased is decorated with that . At the very end, the 'update-refs' step is added to update all of the branches referenced by the 'label' steps. This allows the user to rebase a long list of commits in a multi-part feature and keep all of their pointers to those parts. NOTE: This change only introduce the --update-refs option and implements the changes to the todo file. It does _not_ yet implement the action taken by the 'update-refs' todo step, which will be implemented and tested in a later change. Use the new for_each_decoration() while iterating over the existing todo list. Be sure to iterate after any squashing or fixups are placed. Update the branch only after those squashes and fixups are complete. This allows a --fixup commit at the tip of the feature to apply correctly to the sub branch, even if it is fixing up the most-recent commit in that part. One potential problem here is that refs decorating commits that are already marked as "fixup!" or "squash!" will not be included in this list. Generally, the reordering of the "fixup!" and "squash!" is likely to change the relative order of these refs, so it is not recommended. The workflow here is intended to allow these kinds of commits at the tip of the rebased branch while the other sub branches come along for the ride without intervention. Be careful to not attempt updating any branch that is checked out. The most common example is the branch being rebased is checked out and decorates the tip commit. If the user is rebasing commits reachable from a different branch that is checked out in a different worktree, then they may be surprised to not see that ref update. However, it's probably best to not optimize for this scenario and do the safest thing that will result in a successful rebase. A comment is left in the TODO list that signals that these refs are currently checked out. Signed-off-by: Derrick Stolee --- Documentation/git-rebase.txt | 8 +++ builtin/rebase.c | 5 ++ sequencer.c | 105 ++++++++++++++++++++++++++++++++++ sequencer.h | 1 + t/t3404-rebase-interactive.sh | 72 +++++++++++++++++++++++ 5 files changed, 191 insertions(+) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 262fb01aec0..e7611b4089c 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -609,6 +609,13 @@ provided. Otherwise an explicit `--no-reschedule-failed-exec` at the start would be overridden by the presence of `rebase.rescheduleFailedExec=true` configuration. +--update-refs:: +--no-update-refs:: + Automatically force-update any branches that point to commits that + are being rebased. Any branches that are checked out in a worktree + or point to a `squash! ...` or `fixup! ...` commit are not updated + in this way. + INCOMPATIBLE OPTIONS -------------------- @@ -632,6 +639,7 @@ are incompatible with the following options: * --empty= * --reapply-cherry-picks * --edit-todo + * --update-refs * --root when used in combination with --onto In addition, the following pairs of options are incompatible: diff --git a/builtin/rebase.c b/builtin/rebase.c index 7ab50cda2ad..56d82a52106 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -102,6 +102,7 @@ struct rebase_options { int reschedule_failed_exec; int reapply_cherry_picks; int fork_point; + int update_refs; }; #define REBASE_OPTIONS_INIT { \ @@ -298,6 +299,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) ret = complete_action(the_repository, &replay, flags, shortrevisions, opts->onto_name, opts->onto, &opts->orig_head, &commands, opts->autosquash, + opts->update_refs, &todo_list); } @@ -1124,6 +1126,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "autosquash", &options.autosquash, N_("move commits that begin with " "squash!/fixup! under -i")), + OPT_BOOL(0, "update-refs", &options.update_refs, + N_("update local refs that point to commits " + "that are being rebased")), { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), N_("GPG-sign commits"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, diff --git a/sequencer.c b/sequencer.c index 68f7c76e896..94f8d52e041 100644 --- a/sequencer.c +++ b/sequencer.c @@ -35,6 +35,8 @@ #include "commit-reach.h" #include "rebase-interactive.h" #include "reset.h" +#include "branch.h" +#include "log-tree.h" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" @@ -5614,10 +5616,110 @@ static int skip_unnecessary_picks(struct repository *r, return 0; } +struct todo_add_branch_context { + struct todo_item *items; + size_t items_nr; + size_t items_alloc; + struct strbuf *buf; + struct commit *commit; +}; + +static int add_branch_for_decoration(const struct name_decoration *d, void *data) +{ + struct todo_add_branch_context *ctx = data; + size_t base_offset = ctx->buf->len; + struct todo_item *item; + char *path; + + ALLOC_GROW(ctx->items, + ctx->items_nr + 1, + ctx->items_alloc); + item = &ctx->items[ctx->items_nr]; + memset(item, 0, sizeof(*item)); + + /* If the branch is checked out, then leave a comment instead. */ + if (branch_checked_out(d->name, &path)) { + item->command = TODO_COMMENT; + strbuf_addf(ctx->buf, "# Ref %s checked out at '%s'\n", + d->name, path); + free(path); + } else { + item->command = TODO_LABEL; + strbuf_addf(ctx->buf, "for-update-refs/%s\n", d->name); + } + + item->offset_in_buf = base_offset; + item->arg_offset = base_offset; + item->arg_len = ctx->buf->len - base_offset; + ctx->items_nr++; + + return 0; +} + +/* + * For each 'pick' command, find out if the commit has a decoration in + * refs/heads/. If so, then add a 'label for-update-refs/' command. + */ +static int todo_list_add_update_ref_commands(struct todo_list *todo_list) +{ + int i; + static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP; + static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP; + static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP; + struct decoration_filter decoration_filter = { + .include_ref_pattern = &decorate_refs_include, + .exclude_ref_pattern = &decorate_refs_exclude, + .exclude_ref_config_pattern = &decorate_refs_exclude_config + }; + struct todo_add_branch_context ctx = { + .buf = &todo_list->buf, + }; + + ctx.items_alloc = 2 * todo_list->nr + 1; + ALLOC_ARRAY(ctx.items, ctx.items_alloc); + + string_list_append(&decorate_refs_include, "refs/heads/"); + load_ref_decorations(&decoration_filter, 0); + + for (i = 0; i < todo_list->nr; ) { + struct todo_item *item = &todo_list->items[i]; + + /* insert ith item into new list */ + ALLOC_GROW(ctx.items, + ctx.items_nr + 1, + ctx.items_alloc); + + ctx.items[ctx.items_nr++] = todo_list->items[i++]; + + if (item->commit) { + ctx.commit = item->commit; + for_each_decoration(item->commit, + add_branch_for_decoration, + &ctx); + } + } + + /* Add the "update-refs" step. */ + ALLOC_GROW(ctx.items, + ctx.items_nr + 1, + ctx.items_alloc); + memset(&ctx.items[ctx.items_nr], 0, sizeof(struct todo_item)); + ctx.items[ctx.items_nr].command = TODO_UPDATE_REFS; + ctx.items_nr++; + + free(todo_list->items); + todo_list->items = ctx.items; + todo_list->nr = ctx.items_nr; + todo_list->alloc = ctx.items_alloc; + + return 0; +} + int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags, const char *shortrevisions, const char *onto_name, struct commit *onto, const struct object_id *orig_head, struct string_list *commands, unsigned autosquash, + unsigned update_refs, struct todo_list *todo_list) { char shortonto[GIT_MAX_HEXSZ + 1]; @@ -5636,6 +5738,9 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla item->arg_len = item->arg_offset = item->flags = item->offset_in_buf = 0; } + if (update_refs && todo_list_add_update_ref_commands(todo_list)) + return -1; + if (autosquash && todo_list_rearrange_squash(todo_list)) return -1; diff --git a/sequencer.h b/sequencer.h index c2b4e148d8f..e268208b315 100644 --- a/sequencer.h +++ b/sequencer.h @@ -167,6 +167,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla const char *shortrevisions, const char *onto_name, struct commit *onto, const struct object_id *orig_head, struct string_list *commands, unsigned autosquash, + unsigned update_refs, struct todo_list *todo_list); int todo_list_rearrange_squash(struct todo_list *todo_list); diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index f31afd4a547..5e99ad7f3b6 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1743,6 +1743,78 @@ test_expect_success 'ORIG_HEAD is updated correctly' ' test_cmp_rev ORIG_HEAD test-orig-head@{1} ' +test_expect_success '--update-refs adds label and update-ref commands' ' + git checkout -b update-refs no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + git commit --allow-empty --fixup=third && + git branch -f shared-tip && + ( + set_cat_todo_editor && + + cat >expect <<-EOF && + pick $(git log -1 --format=%h J) J + label for-update-refs/refs/heads/second + label for-update-refs/refs/heads/first + pick $(git log -1 --format=%h K) K + pick $(git log -1 --format=%h L) L + fixup $(git log -1 --format=%h update-refs) fixup! L # empty + label for-update-refs/refs/heads/third + pick $(git log -1 --format=%h M) M + label for-update-refs/refs/heads/no-conflict-branch + label for-update-refs/refs/heads/shared-tip + update-refs + EOF + + test_must_fail git rebase -i --autosquash --update-refs primary >todo && + test_cmp expect todo + ) +' + +test_expect_success '--update-refs adds commands with --rebase-merges' ' + git checkout -b update-refs-with-merge no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + git merge -m merge branch2 && + git branch -f merge-branch && + git commit --fixup=third --allow-empty && + ( + set_cat_todo_editor && + + cat >expect <<-EOF && + label onto + reset onto + pick $(git log -1 --format=%h branch2~1) F + pick $(git log -1 --format=%h branch2) I + label for-update-refs/refs/heads/branch2 + label merge + reset onto + pick $(git log -1 --format=%h refs/heads/second) J + label for-update-refs/refs/heads/second + label for-update-refs/refs/heads/first + pick $(git log -1 --format=%h refs/heads/third~1) K + pick $(git log -1 --format=%h refs/heads/third) L + fixup $(git log -1 --format=%h update-refs-with-merge) fixup! L # empty + label for-update-refs/refs/heads/third + pick $(git log -1 --format=%h HEAD~2) M + label for-update-refs/refs/heads/no-conflict-branch + merge -C $(git log -1 --format=%h HEAD~1) merge # merge + label for-update-refs/refs/heads/merge-branch + update-refs + EOF + + test_must_fail git rebase -i --autosquash \ + --rebase-merges=rebase-cousins \ + --update-refs primary >todo && + + test_cmp expect todo + ) +' + # This must be the last test in this file test_expect_success '$EDITOR and friends are unchanged' ' test_editor_unchanged From patchwork Tue Jun 7 20:42:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872752 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 B4F10CCA482 for ; Wed, 8 Jun 2022 02:46:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378275AbiFHCqk (ORCPT ); Tue, 7 Jun 2022 22:46:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1383658AbiFHCiT (ORCPT ); Tue, 7 Jun 2022 22:38:19 -0400 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD4DB1F0A45 for ; Tue, 7 Jun 2022 13:42:59 -0700 (PDT) Received: by mail-wr1-x42a.google.com with SMTP id p10so25689072wrg.12 for ; Tue, 07 Jun 2022 13:42:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=wUaY4m6wy616wCD/syXAC0m5N0p0jPsQ4bTjvZ2waTE=; b=lejIyonSwF8IqOndXWtGDlo7yRBpd67c7rXOBpMcJzL5LfRdyG3S1i1TsBcOUtWgNF g3PNqfPfjKH3oPJKpXCs1o68E89RTIYpERFgs9Qmv8yEMjngi0FY9WvbIyM1ZYKOcwoR 9+RJ9pA5QVdAO0pWc8r7vXPDCqvatySBBrNyMjUARWf7V2yqEoXOVCjIp4uqnJ++3GC0 8KE34e1gbi5IHHGwwxPREusfocZK73RZJ/Pv5vPEnxrjwTNDE4gFj316o/9qY0oozLyE PY58ohYqlDZEpbqU5wTacwQvS2OgNZkkIrN2ALjRPF4K7hSM0nNmOnmR2h5SXClAmkiP 2AhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=wUaY4m6wy616wCD/syXAC0m5N0p0jPsQ4bTjvZ2waTE=; b=Zb/yLHIXX+4JPzKK4ApyqGk5rJO6hVjwN2oQJFoqjTsixaXwCLP6eR4+ROM4dM3OxT uEvtPTjIeSRc0C7478VYi//O6yRJyGXUMRY1Y9VzRdFvtuwceWl2j6wQrMz2PoYH+Usi 1IkA3izMNiN2tM8SoAPd1I1Xo80lqetPu6n+3XLv5khsOIKbaxWK4KNVc4p1wQRtffLU KkoefG0Kp6bVbQPJ8dVNuPopK+la3nUlqSbJITdzmgvpppOV+LFNoKzb35qZql/TFSB/ Dn9wz+vVhUJbZpfVGDqWaNwsj2o3ASEmOSLi2mjn68MUDPDgFYYWQddZdkogwbEdjMzX Ptlg== X-Gm-Message-State: AOAM531O0b/qBn18nuTXSs0kgjK8MLPo9KdXzv6qJs0pgyCLiII0BRF6 Mf5RO67M7aLd0YEnBgr4znHicKcfxhp3MRzr X-Google-Smtp-Source: ABdhPJxzHaru2ttN6e8+czq4G+VRJfnS/SVrUFbhD5GA4MFujN3CbLr05ulQ5fEkLr78JmsFGqhxaQ== X-Received: by 2002:a5d:6da2:0:b0:20f:d9b6:fc6 with SMTP id u2-20020a5d6da2000000b0020fd9b60fc6mr28778992wrs.479.1654634578137; Tue, 07 Jun 2022 13:42:58 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id m125-20020a1ca383000000b0039c5b4ab1b0sm2326931wme.48.2022.06.07.13.42.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:57 -0700 (PDT) Message-Id: <68f8e51b19c024e1cb075dffd07f81cceaba5957.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:48 +0000 Subject: [PATCH v2 6/7] sequencer: implement 'update-refs' command Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The previous change allowed 'git rebase --update-refs' to create 'label' commands for each branch among the commits being rewritten and add an 'update-refs' command at the end of the todo list. Now, teach Git to update the refs during that final 'update-refs' command. We need to create an array of new and old OIDs for each ref by iterating over the refs/rewritten/for-update-refs/ namespace. We cannot update the refs in-place since this will confuse the refs iterator. Signed-off-by: Derrick Stolee --- sequencer.c | 62 ++++++++++++++++++++++++++++++++++- t/t3404-rebase-interactive.sh | 24 ++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/sequencer.c b/sequencer.c index 94f8d52e041..a8f62ce8e5f 100644 --- a/sequencer.c +++ b/sequencer.c @@ -4061,11 +4061,71 @@ leave_merge: return ret; } -static int do_update_refs(struct repository *r) +struct update_refs_context { + struct ref_store *refs; + char **ref_names; + struct object_id *old; + struct object_id *new; + size_t nr; + size_t alloc; +}; + +static int add_ref_to_context(const char *refname, + const struct object_id *oid, + int flags, + void *data) { + int f = 0; + const char *name; + struct update_refs_context *ctx = data; + + ALLOC_GROW(ctx->ref_names, ctx->nr + 1, ctx->alloc); + ALLOC_GROW(ctx->old, ctx->nr + 1, ctx->alloc); + ALLOC_GROW(ctx->new, ctx->nr + 1, ctx->alloc); + + if (!skip_prefix(refname, "refs/rewritten/for-update-refs/", &name)) + return 1; + + ctx->ref_names[ctx->nr] = xstrdup(name); + oidcpy(&ctx->new[ctx->nr], oid); + if (!refs_resolve_ref_unsafe(ctx->refs, name, 0, + &ctx->old[ctx->nr], &f)) + return 1; + + ctx->nr++; return 0; } +static int do_update_refs(struct repository *r) +{ + int i, res; + struct update_refs_context ctx = { + .refs = get_main_ref_store(r), + .alloc = 16, + }; + ALLOC_ARRAY(ctx.ref_names, ctx.alloc); + ALLOC_ARRAY(ctx.old, ctx.alloc); + ALLOC_ARRAY(ctx.new, ctx.alloc); + + res = refs_for_each_fullref_in(ctx.refs, + "refs/rewritten/for-update-refs/", + add_ref_to_context, + &ctx); + + for (i = 0; !res && i < ctx.nr; i++) + res = refs_update_ref(ctx.refs, "rewritten during rebase", + ctx.ref_names[i], + &ctx.new[i], &ctx.old[i], + 0, UPDATE_REFS_MSG_ON_ERR); + + for (i = 0; i < ctx.nr; i++) + free(ctx.ref_names[i]); + free(ctx.ref_names); + free(ctx.old); + free(ctx.new); + return res; +} + static int is_final_fixup(struct todo_list *todo_list) { int i = todo_list->current; diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 5e99ad7f3b6..72711efec28 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1815,6 +1815,30 @@ test_expect_success '--update-refs adds commands with --rebase-merges' ' ) ' +compare_two_refs () { + git rev-parse $1 >expect && + git rev-parse $2 >actual && + test_cmp expect actual +} + +test_expect_success '--update-refs updates refs correctly' ' + git checkout -B update-refs no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + test_commit extra2 fileX && + git commit --amend --fixup=L && + ( + git rebase -i --autosquash --update-refs primary && + + compare_two_refs HEAD~3 refs/heads/first && + compare_two_refs HEAD~3 refs/heads/second && + compare_two_refs HEAD~1 refs/heads/third && + compare_two_refs HEAD refs/heads/no-conflict-branch + ) +' + # This must be the last test in this file test_expect_success '$EDITOR and friends are unchanged' ' test_editor_unchanged From patchwork Tue Jun 7 20:42:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 12872756 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 AC6C2C433EF for ; Wed, 8 Jun 2022 02:55:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229991AbiFHCzm (ORCPT ); Tue, 7 Jun 2022 22:55:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48114 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1443699AbiFHCxM (ORCPT ); Tue, 7 Jun 2022 22:53:12 -0400 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EEF0C1F0A51 for ; Tue, 7 Jun 2022 13:43:00 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id s1so2591741wra.9 for ; Tue, 07 Jun 2022 13:43:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=tj3V7DMRyQxu6EMFQcaweQWyPvHiWErKetBh7ujjEU8=; b=WYiWchu7h7mbjtNUBx8+6DxK+VUDJ5hLyS158ca0UARvpqAmL2WBphOGl5vnOqaGKB ac50+D2IGSJQcwgHxKLP3SPRy55skfLJZ872SK5XrusiY7A9hKV92GT0YMWoYRoAjVly JsIXRF4c659dlJd0NKJ3sIl8JHLiQIT9HszA0Ycmdkvez2eHASNYzOOn2IJaoy9PUxli 7ZyBGv88RCEcOS2Bbbok6GmcVHoHBFv5n3zDC7OKUYsKDGiutX5egTQjsz6Q8KtwF04t ydCNcfbuntzxEw3hLRIYtqb0vnVTy/O6jzqEDd37JO7/7ku/le58yw7aenyLXxYOjjuW zQyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=tj3V7DMRyQxu6EMFQcaweQWyPvHiWErKetBh7ujjEU8=; b=pfaubSrP6PIi6mWXCPwd3i9DdN49O403AR+6QDajWBgAx4ZsuU1WQkjQ4xedhVnat1 tcmZPSdNidxcNzNvlWfA6VRI1A1c+kEQ7MjtkVnt3ezNA1rytp9VQJSqXxmdlldD2Ydg LYd06GE5Mn0zLXxxmJRFRgRrIr5d0Y6GUfbH/VxhMWIgTgD55A1fFiNgowduGs6m12Pd aGp3s+HO5LcmpLAhZwZVhcFECnSFAM049FRPZsiRsik5JikesXRgoKDemKuIfcgBlWEx GQgjV9H/gpIMM4kg5NO8urPAPwynONlSqQmvqzF+nT7Rje/jkXxMOt9CFN6dyfJi+FKb gR5Q== X-Gm-Message-State: AOAM532bwn/KbepwMt9EWh/5QaTplKY8SJDHGT8SGsAQvX/xyQdnOtFO uGbI4+zagVkTD2Pc5ef7b7Yn7mTavPoUf5WQ X-Google-Smtp-Source: ABdhPJzJ6xy0aRCaPbK+xxMM1o3KVGEiCUY1g6rxQ54GNVuTc1SLmyEL7QXfi0NqRxrHassWv0T2Hg== X-Received: by 2002:adf:ed41:0:b0:210:20a5:26c2 with SMTP id u1-20020adfed41000000b0021020a526c2mr29144499wro.603.1654634579262; Tue, 07 Jun 2022 13:42:59 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id y3-20020a7bcd83000000b0039747cf8354sm20823704wmj.39.2022.06.07.13.42.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 13:42:58 -0700 (PDT) Message-Id: <3d7d3f656b4e93e8caa0d18d29c318ede956d1d7.1654634569.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 07 Jun 2022 20:42:49 +0000 Subject: [PATCH v2 7/7] rebase: add rebase.updateRefs config option Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, johannes.schindelin@gmx.de, me@ttaylorr.com, Jeff Hostetler , Phillip Wood , Elijah Newren , Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The previous change added the --update-refs command-line option. For users who always want this mode, create the rebase.updateRefs config option which behaves the same way as rebase.autoSquash does with the --autosquash option. Signed-off-by: Derrick Stolee --- Documentation/config/rebase.txt | 3 +++ Documentation/git-rebase.txt | 4 ++++ builtin/rebase.c | 5 +++++ t/t3404-rebase-interactive.sh | 14 ++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt index 8c979cb20f2..f19bd0e0407 100644 --- a/Documentation/config/rebase.txt +++ b/Documentation/config/rebase.txt @@ -21,6 +21,9 @@ rebase.autoStash:: `--autostash` options of linkgit:git-rebase[1]. Defaults to false. +rebase.updateRefs:: + If set to true enable `--update-refs` option by default. + rebase.missingCommitsCheck:: If set to "warn", git rebase -i will print a warning if some commits are removed (e.g. a line was deleted), however the diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index e7611b4089c..7a56dbb9bec 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -615,6 +615,10 @@ start would be overridden by the presence of are being rebased. Any branches that are checked out in a worktree or point to a `squash! ...` or `fixup! ...` commit are not updated in this way. ++ +If the `--update-refs` option is enabled by default using the +configuration variable `rebase.updateRefs`, this option can be +used to override and disable this setting. INCOMPATIBLE OPTIONS -------------------- diff --git a/builtin/rebase.c b/builtin/rebase.c index 56d82a52106..8ebc98ea505 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -802,6 +802,11 @@ static int rebase_config(const char *var, const char *value, void *data) return 0; } + if (!strcmp(var, "rebase.updaterefs")) { + opts->update_refs = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "rebase.reschedulefailedexec")) { opts->reschedule_failed_exec = git_config_bool(var, value); return 0; diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 72711efec28..f580afd8723 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1769,6 +1769,12 @@ test_expect_success '--update-refs adds label and update-ref commands' ' EOF test_must_fail git rebase -i --autosquash --update-refs primary >todo && + test_cmp expect todo && + + test_must_fail git -c rebase.autosquash=true \ + -c rebase.updaterefs=true \ + rebase -i primary >todo && + test_cmp expect todo ) ' @@ -1811,6 +1817,14 @@ test_expect_success '--update-refs adds commands with --rebase-merges' ' --rebase-merges=rebase-cousins \ --update-refs primary >todo && + test_cmp expect todo && + + test_must_fail git -c rebase.autosquash=true \ + -c rebase.updaterefs=true \ + rebase -i \ + --rebase-merges=rebase-cousins \ + primary >todo && + test_cmp expect todo ) '