From patchwork Tue Aug 31 02:26:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466267 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF9B6C4320E for ; Tue, 31 Aug 2021 02:26:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B0D9B6101C for ; Tue, 31 Aug 2021 02:26:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239411AbhHaC1k (ORCPT ); Mon, 30 Aug 2021 22:27:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44268 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239376AbhHaC1i (ORCPT ); Mon, 30 Aug 2021 22:27:38 -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 8D3D2C06175F for ; Mon, 30 Aug 2021 19:26:43 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id q14so25107654wrp.3 for ; Mon, 30 Aug 2021 19:26:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=evgH69cGVC9jNNZhiJw0LZ3Qbyh9uA1+LfK/8vbOmaU=; b=t3CdilrU3AC2Ad5pdZcXpS6ed5yLh6jCmPHqR/HBZ4yDJ7PvF66Uz7WsX3WhOUXiLf JryESr3HAHVWNkxWhcM7r6y6jw1qKzARRXdAj/lOKu961nMUn93aQ+GkjXrNXuGnTfVF lqcKzrQv8A1fpb9yIzj+49xEQbFkDDx1Wri/hHuFBPDgJsSyo15NMfXNefKBZNeaA2vK BTtLkJA4mx//KGACsW0q4k47hePiun6YPOiIN7jmr1BYLBSqMpKq8UXI/9geRyUlRJxw ruxCxO5w/h18mmlG2fh62U44bGbL6nqJIn/S+pa91lODXKpuRhsltwZ7FiznLp+OMfx5 Rm5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=evgH69cGVC9jNNZhiJw0LZ3Qbyh9uA1+LfK/8vbOmaU=; b=gTpC4CAPr63icA/RaIOLrwRr7V86wT869pqQ5P1mw9rR6W7gn/6I/VFkL8+mzRLxFn HZUCp8XxmEqDImlBbQXn7i+X0lKs/4df0koYXwVKaCjnYAWK0QBNqr/7Gu5GGOAaY6Z7 o5bRKEVcUqqG2ikFC8YbAadoJiYxCX6oIukUGvLUafarW6Ofr3aF3HE564nUxy71YvRj 7P8wtVyXHO/RwupvWQvssK91bGO/HAa9q0jR0z6k8Tja4rfGDMWn41s/bIrSFUyEtM0g G5Cec6Yx7xMO1phG6+dKGUdI2NzBH4xSFVpte5AN8fyvTbjnnEh+s2twnPyXfImJzaDb 9S/A== X-Gm-Message-State: AOAM5316ntnAM6XD455W9vjRAYcMrw7PawH0D+pCLvhg4UfLyhf1v0O+ tQ3ihkJZi8oDrz8FXlixt8QlQx+hjbI= X-Google-Smtp-Source: ABdhPJz56gn4uatd1EhXH9reimBX7QiLXfpZUg37tuI9AZjFLS2CX9UUHgaSe4D9D7jjMM2wj30Yxw== X-Received: by 2002:a05:6000:128f:: with SMTP id f15mr28614816wrx.262.1630376802212; Mon, 30 Aug 2021 19:26:42 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id w9sm17092349wrs.7.2021.08.30.19.26.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:41 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:34 +0000 Subject: [PATCH 1/7] merge-ort: mark a few more conflict messages as omittable Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren path_msg() has the ability to mark messages as omittable when recording conflict messages in an in-tree file. This conflict message file will then be shown by diffing the merge-created tree to the actual merge commit that is created. While all the messages touched in this commit are very useful when trying to create a merge initially, early use with the --remerge-diff feature (the only user of this omittable conflict message capability), suggests that the particular messages marked in this commit are just noise when trying to see what changes users made to create a merge commit. Mark them as omittable. Signed-off-by: Elijah Newren --- merge-ort.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 515dc39b7f6..4dbf0a477af 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -2409,7 +2409,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt, */ ci->path_conflict = 1; if (pair->status == 'A') - path_msg(opt, new_path, 0, + path_msg(opt, new_path, 1, _("CONFLICT (file location): %s added in %s " "inside a directory that was renamed in %s, " "suggesting it should perhaps be moved to " @@ -2417,7 +2417,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt, old_path, branch_with_new_path, branch_with_dir_rename, new_path); else - path_msg(opt, new_path, 0, + path_msg(opt, new_path, 1, _("CONFLICT (file location): %s renamed to %s " "in %s, inside a directory that was renamed " "in %s, suggesting it should perhaps be " @@ -3814,7 +3814,7 @@ static void process_entry(struct merge_options *opt, reason = _("add/add"); if (S_ISGITLINK(merged_file.mode)) reason = _("submodule"); - path_msg(opt, path, 0, + path_msg(opt, path, 1, _("CONFLICT (%s): Merge conflict in %s"), reason, path); } From patchwork Tue Aug 31 02:26:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466269 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9C404C43214 for ; Tue, 31 Aug 2021 02:26:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7CDBF6102A for ; Tue, 31 Aug 2021 02:26:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239422AbhHaC1l (ORCPT ); Mon, 30 Aug 2021 22:27:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239378AbhHaC1j (ORCPT ); Mon, 30 Aug 2021 22:27:39 -0400 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 25274C061760 for ; Mon, 30 Aug 2021 19:26:44 -0700 (PDT) Received: by mail-wm1-x32e.google.com with SMTP id o39-20020a05600c512700b002e74638b567so1274570wms.2 for ; Mon, 30 Aug 2021 19:26:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=dGJBQ+9lxfP/ACKoQmXCfr25w0hleBh5682flMvpaH4=; b=vTliHpzSDHUpOF/oyshzCiwaKAzisAssXF88vx1mwCycmjXa26hhIhHwIZbpgG52ZJ 0ztxOmdUexEhNCPcxA7w/DwsxL9VYNJ8U/J30VodRxTDIeCG+KlSBExDINL+m2btjGoP jSHT9z420Gvw1g2IngX9y+v1zBr9smTI/TKzD5yQnEWil/fPb8g7KaEPNM5ocbdD45A7 qff1BMkWHftWK8evTPeutbFYgpbP294nPd4DzrwlG2UYnAmRPhQgno0kWRPfxD69e4hu ZiedKmUs/n4KN7hcDETKAF1XOP05pKQ2hWKQW5nhwdRCE02mpirD4BRbePEkTR2ZHbbK NlBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=dGJBQ+9lxfP/ACKoQmXCfr25w0hleBh5682flMvpaH4=; b=Ms1IleQi5lvS1qa2j7n6VK3MRAGeEpqGafUZYeiu7fLMzlBMZRa/7UnsIgb43iNHuh gwvl19hpce7V1VINBJMjipolpO3uWCDJcPeGcWrS4zpGp7vjfbm3tDMGk/czG2HvrqOV GuUc5Jspcenh4tnu5UInQPPD4ioSx5uksC+h4BA8UfRAqKBgsogdMQjl/ejAAhWsO7XZ rojaD+saK5RxWCHIVm3tbrgcprPQBwhf+HPqkq3HoZqXJkF/FCGGzV+RBZn3WEfPkqi+ 8IWM6kWvW0kTpmaROt30Lv4VSEdfjjgz7qE7t3SJtVLrmXGCMLc84cXjJptZQvi+mOug GMeg== X-Gm-Message-State: AOAM531Oxol7l+lbM0LTXwfwNRIUs+NVzIF9HLftv1DXx4Eik4BmBof2 IeQMx9d0p3GVoYIAfH8CLxoooRIiHUs= X-Google-Smtp-Source: ABdhPJycMDBh43Opom8B8NPRQMdI1Vusls/6n3uWKq9ku7fEXHPC8oP1/JwSu43eCE7MKi3aCMsWZQ== X-Received: by 2002:a1c:115:: with SMTP id 21mr1690203wmb.95.1630376802752; Mon, 30 Aug 2021 19:26:42 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l124sm1091746wml.8.2021.08.30.19.26.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:42 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:35 +0000 Subject: [PATCH 2/7] merge-ort: add ability to record conflict messages in a file Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren We want to add an ability for users to run git show --remerge-diff $MERGE_COMMIT or even git log -p --remerge-diff ... and have git show the differences between where the merge machinery would stop and what is recorded in merge commits. However, in such cases, stdout is not an appropriate location to dump conflict messages. Write those messages to a file in the merge result (not to the working tree or index, but just to a blob recorded in the relevant tree object). There are several considerations here: * We have to pick file(s) where we write these conflict messages too * We want to make it as clear as possible that it's not a real file but a set of messages about another file * We want conflict messages about a file to appear near the file in question in a diff, preferably immediately preceding the file in question * Related to the above, per-file conflict messages are preferred over lumping all conflict messages into one big file To achive the above: * We put the conflict messages for $filename in $filename[0:-1] + " " + $filename[-1] + ".conflict_msg" or, in words, we insert a space before the final character of the filename and then also add ".conflict_msg" at the end. * We start the file with a "== Conflict notices for $filename ==" banner Signed-off-by: Elijah Newren --- merge-ort.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++- merge-recursive.c | 3 ++ merge-recursive.h | 1 + 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/merge-ort.c b/merge-ort.c index 4dbf0a477af..a9e69d9cbb0 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -632,7 +632,11 @@ static void path_msg(struct merge_options *opt, const char *fmt, ...) { va_list ap; - struct strbuf *sb = strmap_get(&opt->priv->output, path); + struct strbuf *sb; + + if (opt->record_conflict_msgs_in_tree && omittable_hint) + return; /* Do not record mere hints in tree */ + sb = strmap_get(&opt->priv->output, path); if (!sb) { sb = xmalloc(sizeof(*sb)); strbuf_init(sb, 0); @@ -3531,6 +3535,74 @@ static void write_completed_directory(struct merge_options *opt, info->last_directory_len = strlen(info->last_directory); } +static void put_path_msgs_in_file(struct merge_options *opt, + const char *path, + struct merged_info *mi, + struct directory_versions *dir_metadata) +{ + struct strbuf tmp = STRBUF_INIT, new_path_contents = STRBUF_INIT; + char *new_path; + int new_path_basic_len, unique_counter; + struct merged_info *new_mi; + char final; + struct strbuf *sb = strmap_get(&opt->priv->output, path); + + assert(opt->record_conflict_msgs_in_tree); + if (!sb) + return; + + /* + * Determine a pathname for recording conflict messages. We'd like it + * to sort just before path, but have a name very similar to what path + * has. + */ + strbuf_addstr(&tmp, path); + final = tmp.buf[tmp.len-1]; + strbuf_setlen(&tmp, tmp.len-1); + strbuf_addf(&tmp, " %c.conflict_msg", final); + + /* + * In extremely unlikely event this filename is not unique, modify it + * with "." suffixes until it is. + */ + new_path_basic_len = tmp.len; + unique_counter = 0; + while (strmap_contains(&opt->priv->paths, tmp.buf)) { + strbuf_setlen(&tmp, new_path_basic_len); + strbuf_addf(&tmp, ".%d", ++unique_counter); + } + + /* Now that we have a unique string, move it to our pool */ + new_path = mem_pool_strdup(&opt->priv->pool, tmp.buf); + strbuf_release(&tmp); + + /* Set up contents we want to place in the file. */ + strbuf_addf(&new_path_contents, "== Conflict notices for %s ==\n", + path); + strbuf_addbuf(&new_path_contents, sb); + + /* Set up new_mi */ + new_mi = mem_pool_calloc(&opt->priv->pool, 1, sizeof(*new_mi)); + new_mi->result.mode = 0100644; + new_mi->is_null = 0; + new_mi->clean = 1; + new_mi->basename_offset = mi->basename_offset; + new_mi->directory_name = mi->directory_name; + if (write_object_file(new_path_contents.buf, new_path_contents.len, + blob_type, &new_mi->result.oid)) + die(_("Unable to add %s to database"), new_path); + + /* + * Save new_mi in opt->priv->path (so that something will deallocate + * it later), and record the entry for it. + */ + strmap_put(&opt->priv->paths, new_path, new_mi); + record_entry_for_tree(dir_metadata, new_path, new_mi); + + /* Cleanup */ + strbuf_release(&new_path_contents); +} + /* Per entry merge function */ static void process_entry(struct merge_options *opt, const char *path, @@ -3991,6 +4063,8 @@ static void process_entries(struct merge_options *opt, struct conflict_info *ci = (struct conflict_info *)mi; process_entry(opt, path, ci, &dir_metadata); } + if (!opt->priv->call_depth && opt->record_conflict_msgs_in_tree) + put_path_msgs_in_file(opt, path, mi, &dir_metadata); } trace2_region_leave("merge", "processing", opt->repo); @@ -4226,6 +4300,9 @@ void merge_switch_to_result(struct merge_options *opt, struct string_list olist = STRING_LIST_INIT_NODUP; int i; + if (opt->record_conflict_msgs_in_tree) + BUG("Either display conflict messages or record them in tree, not both"); + trace2_region_enter("merge", "display messages", opt->repo); /* Hack to pre-allocate olist to the desired size */ diff --git a/merge-recursive.c b/merge-recursive.c index 3355d50e8ad..b14fa15be91 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -3697,6 +3697,9 @@ static int merge_start(struct merge_options *opt, struct tree *head) assert(opt->priv == NULL); + /* Not supported; option specific to merge-ort */ + assert(!opt->record_conflict_msgs_in_tree); + /* Sanity check on repo state; index must match head */ if (repo_index_has_changes(opt->repo, head, &sb)) { err(opt, _("Your local changes to the following files would be overwritten by merge:\n %s"), diff --git a/merge-recursive.h b/merge-recursive.h index 0795a1d3ec1..2e2fab37f46 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -46,6 +46,7 @@ struct merge_options { /* miscellaneous control options */ const char *subtree_shift; unsigned renormalize : 1; + unsigned record_conflict_msgs_in_tree : 1; /* internal fields used by the implementation */ struct merge_options_internal *priv; From patchwork Tue Aug 31 02:26:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466271 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E4FDC432BE for ; Tue, 31 Aug 2021 02:26:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 14EFF600CD for ; Tue, 31 Aug 2021 02:26:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239376AbhHaC1m (ORCPT ); Mon, 30 Aug 2021 22:27:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239388AbhHaC1j (ORCPT ); Mon, 30 Aug 2021 22:27:39 -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 B403AC0613D9 for ; Mon, 30 Aug 2021 19:26:44 -0700 (PDT) Received: by mail-wr1-x42a.google.com with SMTP id t15so18889475wrg.7 for ; Mon, 30 Aug 2021 19:26:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=FrzIdksY4AjZzPbnmJBtr6bMZRBR7+W1zkHxlVTT4B0=; b=B2bBspu9zTqmt4OkYxbdefrGgeXbbAFA7rC5mptMtRXaHjrbylrZGXuaeBxZ93l8lK XE9ioQ/B+hwo5VPqsydk6bbKvL+pIkYPFKfwk8xedoCnJOhyaqgRMlMQDrrn8gCzqF4s gJ416jc1UbeCPPX/25iiBlev+9q3t4RV6TI7CU8TLYKHYp7zBNYgyB6xJqpQg05FSMSR Y0sMIbIJwaMMx+GQ34L0kvJ6GtFoBrMQmSE+kS3AWeZ3ebPa/1r+SGWmZFf1GQcZCCow MYmfVzIkYuIH9mNe9TP6OnllBKVK23M8Q18smPQOSTN6U/qcIkwH9xBvFnDPmIm8fCqR zELQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=FrzIdksY4AjZzPbnmJBtr6bMZRBR7+W1zkHxlVTT4B0=; b=nI81XPmrGIrGWHZmYQNRCpcS9Tiiot0Ge0PgybNHjSURytQLr2E/OyT30bwLPX0em9 CNnkDAOC943r8cjSBEpI0EgRv/au/46sGuMa0XTTv5GoHiNHedfRkKdfSqqrPmdrwQ3b FdnT5rk3AgTddYPqy9Y1EYquDEVw4cVkvJcuDOnsZWbJNCvQK0g59ZWK9cnl3SSftvy8 chRbdtQ35eLG4LkBfyNCGPaIh7FOVOVm01/KFCerSbXy+kDzuvHtMIQ/u/CYUe7j/s4k ucFe7dX1WHuobN6IsoQYR3jn9Rhp4Fsz1K+i1YLUAjRLv2rCVEir6varOHVQuQIKR69f 1a9A== X-Gm-Message-State: AOAM531pFLzIagUNcU8hDEKNM+3rY+OLwbGPgLE7gV9lqqJo1y52zNKZ tuCAAnIi4/jcpTar7ck0M3WbcWfKWzI= X-Google-Smtp-Source: ABdhPJxiYjktmhq+2LfS6AEsz/ukNEFMkN9j0V5XF34azKAUH5e+hq/HJRAb8HKbnbL4o0DP8MJz6g== X-Received: by 2002:adf:c449:: with SMTP id a9mr28005458wrg.256.1630376803334; Mon, 30 Aug 2021 19:26:43 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u8sm1093487wmq.45.2021.08.30.19.26.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:43 -0700 (PDT) Message-Id: <2bf5efb5169b71ee7c1da006a74aa67794f1399d.1630376800.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:36 +0000 Subject: [PATCH 3/7] ll-merge: add API for capturing warnings in a strbuf instead of stderr Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Whenever ll-merge encounters a binary file, it prints a warning to stderr. However, for the --remerge-diff option we want to add, we need to capture all conflict messages and show them in a diff instead of dumping them straight to stdout or stderr. Add some new API that will allow us to capture this output and display it in our preferred method. Signed-off-by: Elijah Newren --- ll-merge.c | 51 +++++++++++++++++++++++++++++++++++++++------------ ll-merge.h | 9 +++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/ll-merge.c b/ll-merge.c index 261657578c7..4d5bdc12464 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -11,11 +11,13 @@ #include "run-command.h" #include "ll-merge.h" #include "quote.h" +#include "strbuf.h" struct ll_merge_driver; typedef int (*ll_merge_fn)(const struct ll_merge_driver *, mmbuffer_t *result, + struct strbuf *warnings, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, @@ -51,6 +53,7 @@ void reset_merge_attributes(void) */ static int ll_binary_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, + struct strbuf *warnings, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, @@ -59,6 +62,7 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused, int marker_size) { mmfile_t *stolen; + const char *msg = "Cannot merge binary files: %s (%s vs. %s)"; assert(opts); /* @@ -71,8 +75,11 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused, } else { switch (opts->variant) { default: - warning("Cannot merge binary files: %s (%s vs. %s)", - path, name1, name2); + if (warnings) { + strbuf_addstr(warnings, "Warning: "); + strbuf_addf(warnings, msg, path, name1, name2); + } else + warning(msg, path, name1, name2); /* fallthru */ case XDL_MERGE_FAVOR_OURS: stolen = src1; @@ -98,6 +105,7 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused, static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, + struct strbuf *warnings, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, @@ -114,7 +122,7 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, buffer_is_binary(orig->ptr, orig->size) || buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src2->ptr, src2->size)) { - return ll_binary_merge(drv_unused, result, + return ll_binary_merge(drv_unused, result, warnings, path, orig, orig_name, src1, name1, @@ -138,6 +146,7 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, static int ll_union_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, + struct strbuf *warnings, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, @@ -150,7 +159,7 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused, assert(opts); o = *opts; o.variant = XDL_MERGE_FAVOR_UNION; - return ll_xdl_merge(drv_unused, result, path, + return ll_xdl_merge(drv_unused, result, warnings, path, orig, orig_name, src1, name1, src2, name2, &o, marker_size); } @@ -180,6 +189,7 @@ static void create_temp(mmfile_t *src, char *path, size_t len) */ static int ll_ext_merge(const struct ll_merge_driver *fn, mmbuffer_t *result, + struct strbuf *warnings, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, @@ -362,13 +372,14 @@ static void normalize_file(mmfile_t *mm, const char *path, struct index_state *i } } -int ll_merge(mmbuffer_t *result_buf, - const char *path, - mmfile_t *ancestor, const char *ancestor_label, - mmfile_t *ours, const char *our_label, - mmfile_t *theirs, const char *their_label, - struct index_state *istate, - const struct ll_merge_options *opts) +int ll_merge_with_warnings(mmbuffer_t *result_buf, + struct strbuf *warnings, + const char *path, + mmfile_t *ancestor, const char *ancestor_label, + mmfile_t *ours, const char *our_label, + mmfile_t *theirs, const char *their_label, + struct index_state *istate, + const struct ll_merge_options *opts) { struct attr_check *check = load_merge_attributes(); static const struct ll_merge_options default_opts; @@ -401,11 +412,27 @@ int ll_merge(mmbuffer_t *result_buf, if (opts->extra_marker_size) { marker_size += opts->extra_marker_size; } - return driver->fn(driver, result_buf, path, ancestor, ancestor_label, + return driver->fn(driver, result_buf, warnings, path, + ancestor, ancestor_label, ours, our_label, theirs, their_label, opts, marker_size); } +int ll_merge(mmbuffer_t *result_buf, + const char *path, + mmfile_t *ancestor, const char *ancestor_label, + mmfile_t *ours, const char *our_label, + mmfile_t *theirs, const char *their_label, + struct index_state *istate, + const struct ll_merge_options *opts) +{ + return ll_merge_with_warnings(result_buf, NULL, path, + ancestor, ancestor_label, + ours, our_label, + theirs, their_label, + istate, opts); +} + int ll_merge_marker_size(struct index_state *istate, const char *path) { static struct attr_check *check; diff --git a/ll-merge.h b/ll-merge.h index aceb1b24132..a5469918ad4 100644 --- a/ll-merge.h +++ b/ll-merge.h @@ -96,6 +96,15 @@ int ll_merge(mmbuffer_t *result_buf, struct index_state *istate, const struct ll_merge_options *opts); +int ll_merge_with_warnings(mmbuffer_t *result_buf, + struct strbuf *warnings, + const char *path, + mmfile_t *ancestor, const char *ancestor_label, + mmfile_t *ours, const char *our_label, + mmfile_t *theirs, const char *their_label, + struct index_state *istate, + const struct ll_merge_options *opts); + int ll_merge_marker_size(struct index_state *istate, const char *path); void reset_merge_attributes(void); From patchwork Tue Aug 31 02:26:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466273 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B20D6C4320E for ; Tue, 31 Aug 2021 02:26:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9ED626101C for ; Tue, 31 Aug 2021 02:26:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239403AbhHaC1o (ORCPT ); Mon, 30 Aug 2021 22:27:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239368AbhHaC1j (ORCPT ); Mon, 30 Aug 2021 22:27:39 -0400 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E7A9C061575 for ; Mon, 30 Aug 2021 19:26:45 -0700 (PDT) Received: by mail-wm1-x336.google.com with SMTP id e26so4634762wmk.2 for ; Mon, 30 Aug 2021 19:26:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=N8TOWxc3JZtQX6JZVO9uq92OKX21jlAP9iiHOL50Ay0=; b=ehbIQpeom85Ypgx3tJ/fPkbBapUXpqWvnhzMIOVqaiWY89GJfAerPLPl7eMHPykG6N Qnix8oj4KvebDYXBjSKeq7P/MTbzcmZWZgBkYzla6Le2wWRf6VCGsCzB2Z0OpZpNrG1B UPIQLADedg01+Mzj75LXmGqSp3wVgbI9sUNgFfL+8xOkXbw50sw3pOOb6vUbV7Z8nIOo 32D+Kx2PHxQU5hSiVnK+f7qWWlg27unyQO697aeIJa4r3b1JHsHEx/jxNFvJP92Q8loq AhUWT4ln7Z+KUykupgt/cbmDFaupF8115PrhELzKGuZEKOgYfPULwFgasYL1W06yZ71d 5nSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=N8TOWxc3JZtQX6JZVO9uq92OKX21jlAP9iiHOL50Ay0=; b=mJLnKoabDZ1Z0h0JQZGrmrdH5ANMtdA7GuR4L9QaYZiy9MlmIn95klBQnKNemEYNLs I5SYyENIq5slkfbTIIbwx6feSHSBeEg30FzYq1RwVVW5Got/NOIrcucdp+sFFSPW4i35 a9lpKH4VYR4zVeZLEhPk7bZxZS6dXMq8ZRy0vgFnzNLzx1f/Sk9a51yCFwql2JcdciHl IHmZ+FAKCqa92+uEfjneJ4SoNydfZE+XYtx1AqorSOlnyPNjx6JkGr2yMkN0KQU3YR0t TYvPcTvqdc8J9mGXePYYWnLDNS9E1dmc2mPr7BZYEIfjmqcwFo6qFXH+w9XUY/pWOAPN 39BQ== X-Gm-Message-State: AOAM530lbqF3bo22wd6ul2AJo8ioPjFT5sF2zoroj/qDbF07Zw0uMXDU uZcl2ylGh97Gis0jL7ahn7cMMsMcqXg= X-Google-Smtp-Source: ABdhPJzx2vUEqJMPZTtKY0OE0KyyRxbZ7EZ5+7eGMApbZTe/JH+QXl0tp1K7eNVlOW+4lH44pPWq1w== X-Received: by 2002:a1c:4d10:: with SMTP id o16mr1745019wmh.60.1630376803870; Mon, 30 Aug 2021 19:26:43 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id v28sm16830697wrv.93.2021.08.30.19.26.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:43 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:37 +0000 Subject: [PATCH 4/7] merge-ort: capture and print ll-merge warnings in our preferred fashion Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Instead of immediately printing ll-merge warnings to stderr, we save them in our output strbuf. Besides allowing us to move these warnings to a special file for --remerge-diff, this has two other benefits for regular merges done by merge-ort: * The deferral of messages ensures we can print all messages about any given path together (merge-recursive was known to sometimes intersperse messages about other paths, particularly when renames were involved). * The deferral of messages means we can avoid printing spurious conflict messages when we just end up aborting due to local user modifications in the way. (In contrast to merge-recursive.c which prematurely checks for local modifications in the way via unpack_trees() and gets the check wrong both in terms of false positives and false negatives relative to renames, merge-ort does not perform the local modifications in the way check until the checkout() step after the full merge has been computed.) Signed-off-by: Elijah Newren --- merge-ort.c | 11 ++++++++--- t/t6404-recursive-merge.sh | 10 ++++++++-- t/t6406-merge-attr.sh | 10 ++++++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index a9e69d9cbb0..831f8f3e049 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -1741,6 +1741,7 @@ static int merge_3way(struct merge_options *opt, struct ll_merge_options ll_opts = {0}; char *base, *name1, *name2; int merge_status; + struct strbuf warnings = STRBUF_INIT; if (!opt->priv->attr_index.initialized) initialize_attr_index(opt); @@ -1781,10 +1782,14 @@ static int merge_3way(struct merge_options *opt, read_mmblob(&src1, a); read_mmblob(&src2, b); - merge_status = ll_merge(result_buf, path, &orig, base, - &src1, name1, &src2, name2, - &opt->priv->attr_index, &ll_opts); + merge_status = ll_merge_with_warnings(result_buf, &warnings, path, + &orig, base, + &src1, name1, &src2, name2, + &opt->priv->attr_index, &ll_opts); + if (warnings.len > 0) + path_msg(opt, path, 0, "%s", warnings.buf); + strbuf_release(&warnings); free(base); free(name1); free(name2); diff --git a/t/t6404-recursive-merge.sh b/t/t6404-recursive-merge.sh index eaf48e941e2..a986eec0420 100755 --- a/t/t6404-recursive-merge.sh +++ b/t/t6404-recursive-merge.sh @@ -108,8 +108,14 @@ test_expect_success 'refuse to merge binary files' ' printf "\0\0" >binary-file && git add binary-file && git commit -m binary2 && - test_must_fail git merge F >merge.out 2>merge.err && - grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err + if test "$GIT_TEST_MERGE_ALGORITHM" = ort + then + test_must_fail git merge F >merge.out && + grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.out + else + test_must_fail git merge F >merge.out 2>merge.err && + grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err + fi ' test_expect_success 'mark rename/delete as unmerged' ' diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh index 84946458371..75a7994988a 100755 --- a/t/t6406-merge-attr.sh +++ b/t/t6406-merge-attr.sh @@ -221,8 +221,14 @@ test_expect_success 'binary files with union attribute' ' printf "two\0" >bin.txt && git commit -am two && - test_must_fail git merge bin-main 2>stderr && - grep -i "warning.*cannot merge.*HEAD vs. bin-main" stderr + if test "$GIT_TEST_MERGE_ALGORITHM" = ort + then + test_must_fail git merge bin-main >stdout && + grep -i "warning.*cannot merge.*HEAD vs. bin-main" stdout + else + test_must_fail git merge bin-main 2>stderr && + grep -i "warning.*cannot merge.*HEAD vs. bin-main" stderr + fi ' test_done From patchwork Tue Aug 31 02:26:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466275 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8EEBC432BE for ; Tue, 31 Aug 2021 02:26:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5FCDA61039 for ; Tue, 31 Aug 2021 02:26:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239426AbhHaC1p (ORCPT ); Mon, 30 Aug 2021 22:27:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44284 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239401AbhHaC1k (ORCPT ); Mon, 30 Aug 2021 22:27:40 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC47DC06175F for ; Mon, 30 Aug 2021 19:26:45 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id l7-20020a1c2507000000b002e6be5d86b3so1276653wml.3 for ; Mon, 30 Aug 2021 19:26:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=QI5qretF2TJiQDKwvqhE1t94m4tk2N3sba0TcQX4VT0=; b=Lxnh8Zo0yVfApnas//IC+tppa8rTXv/qiSym81sHcJoWrAQFvGdOqDDVNbIk4V6/TR ZcZHAxqVavJ07kQ36Tdnp9GkxBWNTLs/5fRUN6p6k2ZVzkq3f2CqPw+a3k60Kjh+JzEl 4wm1p4IAVLPxAmYiauQvu3+pgdXWHT4hhID0viUoiSvecFFaPZU++CJiZS8be8BYtmCW URt3GiMr3grYIqcEHV/9E0Qi2kw63JwDYfAq5/M+1+I1gyuHkgxr88q9/QbBrcisc6nL whxIBovUjaAkWz5hUfk791Wkjcq0FFwlASokTTW0F76lSYBzIIMFZQDe/yRN+BnPrdGW i2TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=QI5qretF2TJiQDKwvqhE1t94m4tk2N3sba0TcQX4VT0=; b=jeFs7hn/HXiv6Axtq2jL+PuLlYJEo9cpDmtHFJDzyDToLHVsHHOqYNEWiaH6yY9Z1y m54slgIolyMqZJfUtoF87AYkLXOkvvu97yeXgkfrWKg0OX3dbqPhQG0y8AFzLCekOPpf YxXP8qEY7PaPN2RLSOvAXQRwV+fzjZ/hnuSyRiezLbxkwsUOh1fuLHvygi1Y0jVhBBuY Rh6LOu2mSrwT0pVYYwsl8OARTGCWXgVFb+fD05WXaz3bNjN+y1TBbgMOHXvbUOodHc88 BlUYZc9OVe0JfOybf4Pme3pVfQx7TIhq/gy99CtGcC6ogC90fDnIMhO1xOI9J3/Wcf1l fNAQ== X-Gm-Message-State: AOAM531MO1XIa8+bsgO/TPz+A27z4dfOuAkCt8atrQb1PWH5UUJiiHEY ZXeN0q9KrOSBPzQ6Xj7uuLp+SGrMldY= X-Google-Smtp-Source: ABdhPJwOmOLPjkTNFQBbzqI/oiN71bXLl52fHUCGhZ/AWTpJ98+CnsGjvyJT48ujbnc53f7kHOA1Xg== X-Received: by 2002:a1c:c918:: with SMTP id f24mr1749983wmb.61.1630376804451; Mon, 30 Aug 2021 19:26:44 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id v5sm16562856wrw.44.2021.08.30.19.26.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:44 -0700 (PDT) Message-Id: <67d3b2b09f9ddda616cdd0d1b12ab7afc73670ed.1630376800.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:38 +0000 Subject: [PATCH 5/7] tmp-objdir: new API for creating and removing primary object dirs Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren The tmp_objdir API provides the ability to create temporary object directories, but was designed with the goal of having subprocesses access these object stores, followed by the main process migrating objects from it to the main object store or just deleting it. The subprocesses would view it as their primary datastore and write to it. For the --remerge-diff option we want to add to show & log, we want all writes of intermediate merge results (both blobs and trees) to go to this alternate object store; since those writes will be done by the main process, we need this "alternate" object store to actually be the primary object store. When show & log are done, they'll simply remove this temporary object store. We also need one more thing -- `git log --remerge-diff` can cause the temporary object store to fill up with loose objects. Rather than trying to gc that are known garbage anyway, we simply want to know the location of the temporary object store so we can purge the loose objects after each merge. Signed-off-by: Elijah Newren --- tmp-objdir.c | 29 +++++++++++++++++++++++++++++ tmp-objdir.h | 16 ++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/tmp-objdir.c b/tmp-objdir.c index b8d880e3626..9f75a75d1c0 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -288,7 +288,36 @@ const char **tmp_objdir_env(const struct tmp_objdir *t) return t->env.v; } +const char *tmp_objdir_path(struct tmp_objdir *t) +{ + return t->path.buf; +} + void tmp_objdir_add_as_alternate(const struct tmp_objdir *t) { add_to_alternates_memory(t->path.buf); } + +void tmp_objdir_make_primary(struct repository *r, const struct tmp_objdir *t) +{ + struct object_directory *od; + od = xcalloc(1, sizeof(*od)); + + od->path = xstrdup(t->path.buf); + od->next = r->objects->odb; + r->objects->odb = od; +} + +void tmp_objdir_remove_as_primary(struct repository *r, + const struct tmp_objdir *t) +{ + struct object_directory *od; + + od = r->objects->odb; + if (strcmp(t->path.buf, od->path)) + BUG("expected %s as primary object store; found %s", + t->path.buf, od->path); + r->objects->odb = od->next; + free(od->path); + free(od); +} diff --git a/tmp-objdir.h b/tmp-objdir.h index b1e45b4c75d..6067da24e8c 100644 --- a/tmp-objdir.h +++ b/tmp-objdir.h @@ -19,6 +19,7 @@ * */ +struct repository; struct tmp_objdir; /* @@ -33,6 +34,11 @@ struct tmp_objdir *tmp_objdir_create(void); */ const char **tmp_objdir_env(const struct tmp_objdir *); +/* + * Return the path used for the temporary object directory. + */ +const char *tmp_objdir_path(struct tmp_objdir *t); + /* * Finalize a temporary object directory by migrating its objects into the main * object database, removing the temporary directory, and freeing any @@ -51,4 +57,14 @@ int tmp_objdir_destroy(struct tmp_objdir *); */ void tmp_objdir_add_as_alternate(const struct tmp_objdir *); +/* + * Add the temporary object directory as the *primary* object store in the + * current process, turning the previous primary object store into an + * alternate. + */ +void tmp_objdir_make_primary(struct repository *r, + const struct tmp_objdir *t); +void tmp_objdir_remove_as_primary(struct repository *r, + const struct tmp_objdir *t); + #endif /* TMP_OBJDIR_H */ From patchwork Tue Aug 31 02:26:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466279 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7AE5AC43214 for ; Tue, 31 Aug 2021 02:26:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5A0D16103D for ; Tue, 31 Aug 2021 02:26:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239434AbhHaC1s (ORCPT ); Mon, 30 Aug 2021 22:27:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239417AbhHaC1l (ORCPT ); Mon, 30 Aug 2021 22:27:41 -0400 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E72E1C06175F for ; Mon, 30 Aug 2021 19:26:46 -0700 (PDT) Received: by mail-wr1-x42d.google.com with SMTP id u9so25060313wrg.8 for ; Mon, 30 Aug 2021 19:26:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=mpIlqEaSefaIJHedVnxM1mdqMRclAA+rexyvGVXumD0=; b=ReC5Eh4IR1WKIJcQM0jTl1OCUloN7iVGtZbzx/tYH2p+7L7FTiT/iyPmYQ4r68G5GI S/ex4O/vHAo0bx0jy5UJe44GRhhAzwXoYaz79fmojSjMWhmXOT7L7jjNfIzhFyqpe9n3 feWofPCl5ziCeSB2DPvwMuCdyZZ+ZMT7dTVZyDxYoWZg68QEnMMqBitwfSGbaD5Zprhq P1ohJIuyoV7F0DXnM+SlvlcLkfyvCbL5dZyezBMnwxsbejR+mD+Bg93SViQUrkQ9Qy3B bqEOFAQCwnlLnH9ZqZiGoxWI8jVgKN+MPt4jiXMdvVPMegwLoyW7cazologPVLVFI17I hC2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=mpIlqEaSefaIJHedVnxM1mdqMRclAA+rexyvGVXumD0=; b=Oddmh6+YbfvBdncpqlBbCw61+b6SM+92Udof81o6eeF4CHPMO3Z6OgGMqWyyypmZFS 3vGqm9N8hAXytItApzI090A/xQPmqZx3PRVj9KDI88oWei819RupF+COREn8ewOFS5YX c8Sng96dXyDqzokVihhJMNsTyye74tT9BUzJRlKwIsmRh4x7am4k73D0SaZvK44EG5eB Cg++vsRgq7RDPCH7ThljwIoFOAm41t4qlxJornns5qpKgv1yQxHu/b7xPZ5K474Ab4wU WrCCFeHqE19E3TmJhNd1ImD7alAZjp1aeFUEPzIgbeyAhIQfVuLBNBo10tjit3DORpEm 7H1A== X-Gm-Message-State: AOAM5308q5ZqUljuE1pozTfAQSepysmaPbv/9sFpnNX9NfN0d8V6/bLM Jzfdz6thrShAHRVcS4Z08Uio4eonIhs= X-Google-Smtp-Source: ABdhPJwcfiMbhx1tOwWSI8uQ1CFxJ1dCAKqGBV4m3nfobGHX8nP3lETevAHqFcC3yl7N/kXzk7F6Fg== X-Received: by 2002:adf:a44d:: with SMTP id e13mr27537291wra.177.1630376805043; Mon, 30 Aug 2021 19:26:45 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u2sm1066429wmj.29.2021.08.30.19.26.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:44 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:39 +0000 Subject: [PATCH 6/7] show, log: provide a --remerge-diff capability Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren When this option is specified, we remerge all (two parent) merge commits and diff the actual merge commit to the automatically created version, in order to show how users removed conflict markers, resolved the different conflict versions, and potentially added new changes outside of conflict regions in order to resolve semantic merge problems (or, possibly, just to hide other random changes). This capability works by creating a temporary object directory and marking it as the primary object store, so that any blobs or trees created during the automatic merge, can be easily removed afterwards by just deleting all objects from the temporary object directory. We can do this after handling each merge commit, in order to avoid the need to worry about doing `git gc --auto` runs while running `git log --remerge-diff`. Signed-off-by: Elijah Newren --- builtin/log.c | 23 +++++++++++++++++ diff-merges.c | 12 +++++++++ log-tree.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ revision.h | 6 ++++- 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/builtin/log.c b/builtin/log.c index 3d7717ba5ca..6c7288716e6 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -35,6 +35,8 @@ #include "repository.h" #include "commit-reach.h" #include "range-diff.h" +#include "dir.h" +#include "tmp-objdir.h" #define MAIL_DEFAULT_WRAP 72 #define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100 @@ -51,6 +53,7 @@ static int default_encode_email_headers = 1; static int decoration_style; static int decoration_given; static int use_mailmap_config = 1; +static struct tmp_objdir *tmp_objdir; static const char *fmt_patch_subject_prefix = "PATCH"; static int fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT; static const char *fmt_pretty; @@ -407,6 +410,17 @@ static int cmd_log_walk(struct rev_info *rev) int saved_nrl = 0; int saved_dcctc = 0; + if (rev->remerge_diff) { + tmp_objdir = tmp_objdir_create(); + if (!tmp_objdir) + die(_("unable to create temporary object directory")); + tmp_objdir_make_primary(the_repository, tmp_objdir); + + strbuf_init(&rev->remerge_objdir_location, 0); + strbuf_addstr(&rev->remerge_objdir_location, + tmp_objdir_path(tmp_objdir)); + } + if (rev->early_output) setup_early_output(); @@ -449,6 +463,13 @@ static int cmd_log_walk(struct rev_info *rev) rev->diffopt.no_free = 0; diff_free(&rev->diffopt); + if (rev->remerge_diff) { + strbuf_release(&rev->remerge_objdir_location); + tmp_objdir_remove_as_primary(the_repository, tmp_objdir); + tmp_objdir_destroy(tmp_objdir); + tmp_objdir = NULL; + } + if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF && rev->diffopt.flags.check_failed) { return 02; @@ -1943,6 +1964,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die(_("--name-status does not make sense")); if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) die(_("--check does not make sense")); + if (rev.remerge_diff) + die(_("--remerge_diff does not make sense")); if (!use_patch_format && (!rev.diffopt.output_format || diff --git a/diff-merges.c b/diff-merges.c index d897fd8a293..3a24c45b8e5 100644 --- a/diff-merges.c +++ b/diff-merges.c @@ -17,6 +17,7 @@ static void suppress(struct rev_info *revs) revs->combined_all_paths = 0; revs->merges_imply_patch = 0; revs->merges_need_diff = 0; + revs->remerge_diff = 0; } static void set_separate(struct rev_info *revs) @@ -45,6 +46,12 @@ static void set_dense_combined(struct rev_info *revs) revs->dense_combined_merges = 1; } +static void set_remerge_diff(struct rev_info *revs) +{ + suppress(revs); + revs->remerge_diff = 1; +} + static diff_merges_setup_func_t func_by_opt(const char *optarg) { if (!strcmp(optarg, "off") || !strcmp(optarg, "none")) @@ -57,6 +64,8 @@ static diff_merges_setup_func_t func_by_opt(const char *optarg) return set_combined; else if (!strcmp(optarg, "cc") || !strcmp(optarg, "dense-combined")) return set_dense_combined; + else if (!strcmp(optarg, "r") || !strcmp(optarg, "remerge")) + return set_remerge_diff; else if (!strcmp(optarg, "m") || !strcmp(optarg, "on")) return set_to_default; return NULL; @@ -113,6 +122,9 @@ int diff_merges_parse_opts(struct rev_info *revs, const char **argv) } else if (!strcmp(arg, "--cc")) { set_dense_combined(revs); revs->merges_imply_patch = 1; + } else if (!strcmp(arg, "--remerge-diff")) { + set_remerge_diff(revs); + revs->merges_imply_patch = 1; } else if (!strcmp(arg, "--no-diff-merges")) { suppress(revs); } else if (!strcmp(arg, "--combined-all-paths")) { diff --git a/log-tree.c b/log-tree.c index 6dc4412268b..ed69a4da140 100644 --- a/log-tree.c +++ b/log-tree.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "commit-reach.h" #include "config.h" #include "diff.h" #include "object-store.h" @@ -7,6 +8,7 @@ #include "tag.h" #include "graph.h" #include "log-tree.h" +#include "merge-ort.h" #include "reflog-walk.h" #include "refs.h" #include "string-list.h" @@ -16,6 +18,7 @@ #include "line-log.h" #include "help.h" #include "range-diff.h" +#include "dir.h" static struct decoration name_decoration = { "object names" }; static int decoration_loaded; @@ -902,6 +905,60 @@ static int do_diff_combined(struct rev_info *opt, struct commit *commit) return !opt->loginfo; } +static int do_remerge_diff(struct rev_info *opt, + struct commit_list *parents, + struct object_id *oid, + struct commit *commit) +{ + struct merge_options o; + struct commit_list *bases; + struct merge_result res; + struct pretty_print_context ctx = {0}; + struct strbuf commit1 = STRBUF_INIT; + struct strbuf commit2 = STRBUF_INIT; + + /* Setup merge options */ + init_merge_options(&o, the_repository); + memset(&res, 0, sizeof(res)); + o.show_rename_progress = 0; + + ctx.abbrev = DEFAULT_ABBREV; + format_commit_message(parents->item, "%h (%s)", &commit1, &ctx); + format_commit_message(parents->next->item, "%h (%s)", &commit2, &ctx); + o.branch1 = commit1.buf; + o.branch2 = commit2.buf; + o.record_conflict_msgs_in_tree = 1; + + /* Parse the relevant commits and get the merge bases */ + parse_commit_or_die(parents->item); + parse_commit_or_die(parents->next->item); + bases = get_merge_bases(parents->item, parents->next->item); + + /* Re-merge the parents */ + merge_incore_recursive(&o, + bases, parents->item, parents->next->item, + &res); + + /* Show the diff */ + diff_tree_oid(&res.tree->object.oid, oid, "", &opt->diffopt); + log_tree_diff_flush(opt); + + /* Cleanup */ + strbuf_release(&commit1); + strbuf_release(&commit2); + merge_finalize(&o, &res); + + /* Clean up the temporary object directory */ + if (opt->remerge_objdir_location.buf != NULL && + *opt->remerge_objdir_location.buf != '\0') + remove_dir_recursively(&opt->remerge_objdir_location, + REMOVE_DIR_KEEP_TOPLEVEL); + else + BUG("unable to remove temporary object directory"); + + return !opt->loginfo; +} + /* * Show the diff of a commit. * @@ -936,6 +993,18 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log } if (is_merge) { + int octopus = (parents->next->next != NULL); + + if (opt->remerge_diff) { + if (octopus) { + show_log(opt); + fprintf(opt->diffopt.file, + "diff: warning: Skipping remerge-diff " + "for octopus merges.\n"); + return 1; + } + return do_remerge_diff(opt, parents, oid, commit); + } if (opt->combine_merges) return do_diff_combined(opt, commit); if (opt->separate_merges) { diff --git a/revision.h b/revision.h index fbb068da9fb..d6562c52252 100644 --- a/revision.h +++ b/revision.h @@ -198,7 +198,8 @@ struct rev_info { combine_merges:1, combined_all_paths:1, dense_combined_merges:1, - first_parent_merges:1; + first_parent_merges:1, + remerge_diff:1; /* Format info */ int show_notes; @@ -320,6 +321,9 @@ struct rev_info { /* misc. flags related to '--no-kept-objects' */ unsigned keep_pack_cache_flags; + + /* Location where temporary objects for remerge-diff are written. */ + struct strbuf remerge_objdir_location; }; int ref_excluded(struct string_list *, const char *path); From patchwork Tue Aug 31 02:26:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12466277 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75A9CC4320A for ; Tue, 31 Aug 2021 02:26:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5F70A61039 for ; Tue, 31 Aug 2021 02:26:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239412AbhHaC1q (ORCPT ); Mon, 30 Aug 2021 22:27:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239416AbhHaC1l (ORCPT ); Mon, 30 Aug 2021 22:27:41 -0400 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE0E1C061575 for ; Mon, 30 Aug 2021 19:26:46 -0700 (PDT) Received: by mail-wm1-x32c.google.com with SMTP id g138so10041835wmg.4 for ; Mon, 30 Aug 2021 19:26:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=1KZlym63hsEmgZKhgF68sGOhw4+6yJaaNBmMEKsLv5I=; b=pF1N86GXOkmd8SEN2rslN5p6fPEcQGZuPPCM3gA7wygxHEBcLnr9KojiOJSff1EcQh J6QBYKUDRS9GWBR1WOIGPwvJ5j8cERHCS6Udr8bl6PDR+pXaeiuJwGs5ne7YSOn7j43w pqzddG1OMEuNvH5oxz+LkaLIYSm2BjAA7qlJm6Vst4wBhztdo2Ghv/Xl/5CHu3z+ff99 1OOHwygUvzK18oBMiPWz08lS5M8o4E0ls2jvoHv2Agqe/GbmhNmVl1bf3dG7WkLaKhOf 7c7/0Bry1f1gQF5pqLVzCNgM3VxKAPsnGjpTt6gHOrk0gBK65gZMPrEirsOwzN44Zjju cAcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=1KZlym63hsEmgZKhgF68sGOhw4+6yJaaNBmMEKsLv5I=; b=QLEB8xO0CH9uxNqhLgCs9NaRxQJ7oHxBvR1Yr4SYJixLODTHKy+xL/H6YsswgbgKRs g9PLtKjFCpLeN2ghzhi/g9xwYDPvCxDmobKPTklO+1hUm/gEapi+g/yZh1mEMstjZ8DJ NISvz9/5k8vezu5NzIoQcnZqKhfxCeaBuxs+uYKulswhqzVMrcouiQ/8fx2+dMp8FNtw i92k2CWkFzp6KCmjAiyPZvpWnkvSbdLZ+2JBB1jly8uwM2xl1jWI52h2w0nOwDOoa1CG 7wxdLzBSi9E8b9/Mc8nNvfTvoTFr02UPNg3inR3bhAqyw7ANjqJB9y2xV824T5EyGTfa zvDg== X-Gm-Message-State: AOAM533aa7OskMXeACmp66hI6eCL1XovZsFKA+4xVLKgr9SIe8iBmIxX P2IGUTgFsaVzY8w5LeJGUMh/8WPJP84= X-Google-Smtp-Source: ABdhPJy/9PiOnR7bjxgxMs0/4dAvM8XeDcBfq0YHctugHo3gnvBxmJiwTxGdryx70WQsl2CRbbCt/Q== X-Received: by 2002:a1c:f414:: with SMTP id z20mr1738378wma.94.1630376805555; Mon, 30 Aug 2021 19:26:45 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n5sm1048192wmd.29.2021.08.30.19.26.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Aug 2021 19:26:45 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Tue, 31 Aug 2021 02:26:40 +0000 Subject: [PATCH 7/7] doc/diff-options: explain the new --remerge-diff option Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , Jonathan Nieder , Sergey Organov , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Signed-off-by: Elijah Newren --- Documentation/diff-options.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index c89d530d3d1..b05f1c9f1c9 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -64,6 +64,14 @@ ifdef::git-log[] each of the parents. Separate log entry and diff is generated for each parent. + +--diff-merges=remerge::: +--diff-merges=r::: +--remerge-diff::: + With this option, two-parent merge commits are remerged to + create a temporary tree object -- potentially containing files + with conflict markers and such. A diff is then shown between + that temporary tree and the actual merge commit. ++ --diff-merges=combined::: --diff-merges=c::: -c:::