From patchwork Thu Feb 23 07:29:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Teng Long X-Patchwork-Id: 13149907 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 0E72BC64ED8 for ; Thu, 23 Feb 2023 07:30:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233336AbjBWHaA (ORCPT ); Thu, 23 Feb 2023 02:30:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232865AbjBWH35 (ORCPT ); Thu, 23 Feb 2023 02:29:57 -0500 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7B8B3251F for ; Wed, 22 Feb 2023 23:29:56 -0800 (PST) Received: by mail-pl1-x636.google.com with SMTP id ky4so12955092plb.3 for ; Wed, 22 Feb 2023 23:29:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LeIMhcbJ2DVoI7uyk5qxWZf5i6kxq56B6BUvacGWnC4=; b=FVkTnFTwtRvchGLDn7e/xaAEnb6CgXEhASgw+zJrhV//h7SJpk3K/gwGUqcVSHbWVa HbwdgvtKBrUyYjrxoop5q0M4Co8VEORIUSElFP/LdychyeYTpZ/HQ9Ol6tXC64O27etz z8RWIXShLqlxpggtyppJlKpTRGbnjyYNEf1U2M8hgwrJamDdhQJuMJXltS1lMLgndPIF ZeT4JcohLuHzSP8HmcsMApPe2MaVEhg0U122zb29On/PUNSIn3TxIwW2LOhFc9FODNdZ xfjt2h9VBYyDyI1qH5hGjPQZX4yYIjlutMr0PIXT9WH0zXlsxdEv656e2OpLn9dWr4++ SiNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LeIMhcbJ2DVoI7uyk5qxWZf5i6kxq56B6BUvacGWnC4=; b=n8pO/P4UNJKopWAyyq2hO2of7xz8AqnfMGF8mDxkKHfkWYUpt0yL21VadIYOIgz1Kn hXywGhJ++ZXyQLmIJasGTmStPOHVVMu4a8wImtVhpsH3pQZnZemmuoI31cl8EeuTZb2A wfpr1in1owLJyycXImdvp4y57HevsaOAFRglVVSLV0WKi3dYv1v8fJ70IKcuFyDSDtuK BfJ6zpeZVDTa10elV1wjpdfjWucyB10ZibCLfvXMer9A/S6eF5lFje6qyalQcJe+9bJH WZIq7DSWf44Jr7c5pRQQqqb3TyseB4GGlcGftYVzT76CxVtMZEmEwU9HVjbOOjWA6cgA vGfg== X-Gm-Message-State: AO0yUKVG0O9Jkhcc6g003qNzzsx0ZvCgxhUDv+9H/w81m2kGcdJYq1Xd 5mdqfrBsBdoLUHGt4gVLwBU= X-Google-Smtp-Source: AK7set9w7XEyIJAyN1pWgr6Jy96Q8qmuqyojzAjDSSMJl1U4nGl5hMelLZ+khfGnkkmy2LVC3F8ojw== X-Received: by 2002:a05:6a20:7f9c:b0:cc:24de:6a72 with SMTP id d28-20020a056a207f9c00b000cc24de6a72mr1227716pzj.61.1677137396294; Wed, 22 Feb 2023 23:29:56 -0800 (PST) Received: from localhost.localdomain ([47.246.101.50]) by smtp.gmail.com with ESMTPSA id u20-20020a62ed14000000b0059085684b54sm5570364pfh.140.2023.02.22.23.29.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Feb 2023 23:29:55 -0800 (PST) From: Teng Long X-Google-Original-From: Teng Long To: dyroneteng@gmail.com Cc: avarab@gmail.com, git@vger.kernel.org, sunshine@sunshineco.com, tenglong.tl@alibaba-inc.com, gitster@pobox.com Subject: [PATCH v6 1/3] notes.c: cleanup 'strbuf_grow' call in 'append_edit' Date: Thu, 23 Feb 2023 15:29:45 +0800 Message-Id: X-Mailer: git-send-email 2.39.2.459.gd5a6c747 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Teng Long Let's cleanup the unnecessary 'strbuf_grow' call in 'append_edit'. This "strbuf_grow(&d.buf, size + 1);" is prepared for insert a blank line if needed, but actually when inserting, "strbuf_insertstr(&d.buf, 0, "\n");" will do the "grow" for us. 348f199b (builtin-notes: Refactor handling of -F option to allow combining -m and -F, 2010-02-13) added these to mimic the code introduced by 2347fae5 (builtin-notes: Add "append" subcommand for appending to note objects, 2010-02-13) that reads in previous note before the message. And the resulting code with explicit sizing is carried to this day. In the context of reading an existing note in, exact sizing may have made sense, but because the resulting note needs cleansing with stripspace() when appending with this option, such an exact sizing does not buy us all that much in practice. It may help avoiding overallocation due to ALLOC_GROW() slop, but nobody can feed so many long messages for it to matter from the command line. Signed-off-by: Teng Long Helped-by: Eric Sunshine Helped-by: Junio C Hamano --- builtin/notes.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/builtin/notes.c b/builtin/notes.c index 80d9dfd2..23cb6f0d 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -215,7 +215,6 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset) BUG_ON_OPT_NEG(unset); - strbuf_grow(&d->buf, strlen(arg) + 2); if (d->buf.len) strbuf_addch(&d->buf, '\n'); strbuf_addstr(&d->buf, arg); @@ -618,7 +617,6 @@ static int append_edit(int argc, const char **argv, const char *prefix) enum object_type type; char *prev_buf = read_object_file(note, &type, &size); - strbuf_grow(&d.buf, size + 1); if (d.buf.len && prev_buf && size) strbuf_insertstr(&d.buf, 0, "\n"); if (prev_buf && size) From patchwork Thu Feb 23 07:29:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Teng Long X-Patchwork-Id: 13149906 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 D1D02C636D7 for ; Thu, 23 Feb 2023 07:30:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233371AbjBWHaC (ORCPT ); Thu, 23 Feb 2023 02:30:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39164 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233276AbjBWH37 (ORCPT ); Thu, 23 Feb 2023 02:29:59 -0500 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BCEBF32537 for ; Wed, 22 Feb 2023 23:29:58 -0800 (PST) Received: by mail-pg1-x532.google.com with SMTP id d10so1860464pgt.12 for ; Wed, 22 Feb 2023 23:29:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jqqANCJ/5EbUxhX1q6md/iiNuYrqr/dW0kGua/uzH0k=; b=Qm67N53DEcdAAIQ52qQChaaAnpZg8jsbkjvoUvHpnrztEPxfcxhF9GmcQTHLPHQS4H kJ+Q1Vd3D4+jxPAfn2q6B7hq2dRJ7+F234sI4Blk+Eh/hmU5I8TmRNOTrQjzxH20B73S Ym/Q9AKTybPPBFW2dhnJ2By5ojztxjnmtwXSvzlfTJr0SOnTISbCNS93NtOm83Xv5K8e VFzzpKwtJXSdHrOS9cs2+WOgKLzvjJrANV6+1f4FuslNbnFuwiSCQM7nPPbkUgsYymFO MqmJQqpYEuclPa++jfwjA3d7foOqMD0Qt4BNrwSSanxm7k6YopYamrrMnW3f35PyIyLc 2/Cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jqqANCJ/5EbUxhX1q6md/iiNuYrqr/dW0kGua/uzH0k=; b=HYdsoa8xBTLuhJwMLVezU/UCfcCjh71Pi2ZzKICbC1zlhnyvjnm5t58+pGQNPEcXo2 2KQUUii+HqePgNRx3f/9yvfTpUkUzfJFSCbeF1aUSe54wSpkWlJfVB6R6LLtX3h/Hthp 4j5aRvCY+hoqDtJVUsWaJwlXb9/hQPfKmQD0M3F9aiGfRP1eboMoywvj68ac5xUHEAde drzAJchoKQI/jqe79GuRGVagT+BFJrj5hdxRWPB3kG9IKHrDhvgd1qz8bbFnYDJAxalR xWyqgFtYwODXFpL2w6NF/LdcM6TmzlXuP9JVqvyZrJ2uJq36u217sm5CSgYSRp6OpJ0x JFjg== X-Gm-Message-State: AO0yUKU7Tx3Ygq6LASEymniNg35RU0/evho7HSomNlswCr4nxDsLk3G4 qNnOmM4rWtlgMVDHK3/+bGg= X-Google-Smtp-Source: AK7set/5IBZwbaNMmNMX4mwcLdhzjGysw0TS6K9XGyTjujjQSFh9EN9aRwe+re1M+6HCBRsbOHg1SQ== X-Received: by 2002:aa7:96ae:0:b0:5db:bc21:8dfa with SMTP id g14-20020aa796ae000000b005dbbc218dfamr1446114pfk.19.1677137398245; Wed, 22 Feb 2023 23:29:58 -0800 (PST) Received: from localhost.localdomain ([47.246.101.50]) by smtp.gmail.com with ESMTPSA id u20-20020a62ed14000000b0059085684b54sm5570364pfh.140.2023.02.22.23.29.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Feb 2023 23:29:57 -0800 (PST) From: Teng Long X-Google-Original-From: Teng Long To: dyroneteng@gmail.com Cc: avarab@gmail.com, git@vger.kernel.org, sunshine@sunshineco.com, tenglong.tl@alibaba-inc.com, gitster@pobox.com Subject: [PATCH v6 2/3] notes.c: cleanup for "designated init" Date: Thu, 23 Feb 2023 15:29:46 +0800 Message-Id: <043db6311b0af9311764d8e763e85867ed3381a6.1677136319.git.dyroneteng@gmail.com> X-Mailer: git-send-email 2.39.2.459.gd5a6c747 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Teng Long The "struct note_data d = { 0, 0, NULL, STRBUF_INIT };" style could be replaced with designated init format. Signed-off-by: Teng Long --- builtin/notes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/notes.c b/builtin/notes.c index 23cb6f0d..553ae2bd 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -401,7 +401,7 @@ static int add(int argc, const char **argv, const char *prefix) struct notes_tree *t; struct object_id object, new_note; const struct object_id *note; - struct note_data d = { 0, 0, NULL, STRBUF_INIT }; + struct note_data d = { .buf = STRBUF_INIT }; struct option options[] = { OPT_CALLBACK_F('m', "message", &d, N_("message"), N_("note contents as a string"), PARSE_OPT_NONEG, @@ -567,7 +567,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) const struct object_id *note; char *logmsg; const char * const *usage; - struct note_data d = { 0, 0, NULL, STRBUF_INIT }; + struct note_data d = { .buf = STRBUF_INIT }; struct option options[] = { OPT_CALLBACK_F('m', "message", &d, N_("message"), N_("note contents as a string"), PARSE_OPT_NONEG, From patchwork Thu Feb 23 07:29:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Teng Long X-Patchwork-Id: 13149909 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 20B34C6379F for ; Thu, 23 Feb 2023 07:30:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233493AbjBWHaH (ORCPT ); Thu, 23 Feb 2023 02:30:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39224 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233276AbjBWHaD (ORCPT ); Thu, 23 Feb 2023 02:30:03 -0500 Received: from mail-pf1-x42f.google.com (mail-pf1-x42f.google.com [IPv6:2607:f8b0:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 55F2032E41 for ; Wed, 22 Feb 2023 23:30:01 -0800 (PST) Received: by mail-pf1-x42f.google.com with SMTP id f11so5713560pfe.2 for ; Wed, 22 Feb 2023 23:30:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lTmQ2D0GYskHZINr9pdOOdredVXz+J37y162csW7Lkk=; b=QtXskS+0DKatCUhBuCGW2dnsM8a0Jqg5Z3pozhIwGnXJ70zKa691EtPsRWpgofssEx ZyQrWaUVqRB8XCTJ7VMrDLWyaHpBFnOerHibO/tbLjmz3f0GNLt/Gf3g/wvS9UCt5IKz MpTo/wVd/U1pGCo3D3GYNU/jvCqhf1IEV1q1Rfgo/VMJXK1OyHh8KuLT2Yn38zkm0u6U B4LVTRjaKAcXapZeuW1OG3dOkl8GasOHfncSEy09DRNqhn1IvDIKDbeIp0bSSPeYKjyC Thuc9n7rM8yI1YWRYpjCt5iXgg7TvubBPRwuUD2UjTXuMS6fDbyF8TFOA8qJ0QzRSDYQ THuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lTmQ2D0GYskHZINr9pdOOdredVXz+J37y162csW7Lkk=; b=LAZk7gv8USSvZ6I1qmiIScITyGQrNzV3QibwkadQn4G91/HjHKdHIKvZpNaI/EAyvv n/VMlHz/NITU/pzOdwaG+AmXb3IXag8RYlnyeA37KFNWoF0IWQ/om/Su/vCu06cMR+jC 37gmGyxACUcU62tJkQ2AcxzGqW+CJtijm01+QiT8YxswScK1M8erC8B0+c1ANOtAun2L d+tjd9eO8nasjy/5+eYzxNj5ww2pPlsepxPoXQfKLejyZFxWO3xJpZYynxrGOghk77i0 EtJIYCx4expvbM4waGQ081S+ad476Pz93gq2EXAX/9S0T+5TUSgJ04Bw18xh6cy9/MMT IwxA== X-Gm-Message-State: AO0yUKW0BVyGk4z4fs6gq2cuMPWI8igVZNt1p51FvRmo69LI/UPM0tL8 j7+akM1vvBrH4SXXxOQ8uwk= X-Google-Smtp-Source: AK7set9LuohTgl6c1GkSJCkQz4Z6wzU/m3d7l+owbRE9NAFbFh2Gx5Bqv+cIVTgn5z0OxIDw1uWpAA== X-Received: by 2002:a62:17c1:0:b0:593:c9b6:dc5d with SMTP id 184-20020a6217c1000000b00593c9b6dc5dmr10494371pfx.0.1677137400177; Wed, 22 Feb 2023 23:30:00 -0800 (PST) Received: from localhost.localdomain ([47.246.101.50]) by smtp.gmail.com with ESMTPSA id u20-20020a62ed14000000b0059085684b54sm5570364pfh.140.2023.02.22.23.29.58 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Feb 2023 23:29:59 -0800 (PST) From: Teng Long X-Google-Original-From: Teng Long To: dyroneteng@gmail.com Cc: avarab@gmail.com, git@vger.kernel.org, sunshine@sunshineco.com, tenglong.tl@alibaba-inc.com, gitster@pobox.com Subject: [PATCH v6 3/3] notes.c: introduce '--separator=' option Date: Thu, 23 Feb 2023 15:29:47 +0800 Message-Id: X-Mailer: git-send-email 2.39.2.459.gd5a6c747 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Teng Long When adding new notes or appending to an existing notes, we will insert a blank line between the paragraphs, like: $ git notes add -m foo -m bar $ git notes show HEAD | cat foo bar The default behavour sometimes is not enough, the user may want to use a custom delimiter between paragraphs, like when specifiy one or more '-m' or '-F' options. So this commit introduces a new '--separator' option for 'git-notes-add' and 'git-notes-append', for example when execute: $ git notes add -m foo -m bar --separator="-" $ git notes show HEAD | cat foo - bar We will check the option value and if the value doesn't contail a trailing '\n', will add it automatically, so execute $ git notes add -m foo -m bar --separator="-" and $ export LF=" " $ git notes add -m foo -m bar --separator="-$LF" have the same behavour. Signed-off-by: Teng Long --- Documentation/git-notes.txt | 20 ++++++-- builtin/notes.c | 72 ++++++++++++++++++-------- t/t3301-notes.sh | 100 ++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 26 deletions(-) diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index efbc10f0..53d63888 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -9,9 +9,9 @@ SYNOPSIS -------- [verse] 'git notes' [list []] -'git notes' add [-f] [--allow-empty] [-F | -m | (-c | -C) ] [] +'git notes' add [-f] [--allow-empty] [--separator=] [-F | -m | (-c | -C) ] [] 'git notes' copy [-f] ( --stdin | [] ) -'git notes' append [--allow-empty] [-F | -m | (-c | -C) ] [] +'git notes' append [--allow-empty] [--separator=] [-F | -m | (-c | -C) ] [] 'git notes' edit [--allow-empty] [] 'git notes' show [] 'git notes' merge [-v | -q] [-s ] @@ -65,7 +65,9 @@ add:: However, if you're using `add` interactively (using an editor to supply the notes contents), then - instead of aborting - the existing notes will be opened in the editor (like the `edit` - subcommand). + subcommand). If you specify multiple `-m` and `-F`, a blank + line will be inserted between the messages. Use the `--separator` + option to insert other delimiters. copy:: Copy the notes for the first object onto the second object (defaults to @@ -86,7 +88,13 @@ the command can read the input given to the `post-rewrite` hook.) append:: Append to the notes of an existing object (defaults to HEAD). - Creates a new notes object if needed. + Creates a new notes object if needed. + The default delimiter is a blank line, use the `--separator` + option to insert other delimiters. More specifically, if the + note and the message are not empty, the delimiter will be + inserted between them. If you specify multiple `-m` and `-F` + options, the delimiter will be inserted between the messages + too. edit:: Edit the notes for a given object (defaults to HEAD). @@ -159,6 +167,10 @@ OPTIONS Allow an empty note object to be stored. The default behavior is to automatically remove empty notes. +--separator :: + The '' inserted between paragraphs. + A blank line by default. + --ref :: Manipulate the notes tree in . This overrides `GIT_NOTES_REF` and the "core.notesRef" configuration. The ref diff --git a/builtin/notes.c b/builtin/notes.c index 553ae2bd..e0ada862 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -24,11 +24,12 @@ #include "notes-utils.h" #include "worktree.h" +static char *separator = NULL; static const char * const git_notes_usage[] = { N_("git notes [--ref ] [list []]"), - N_("git notes [--ref ] add [-f] [--allow-empty] [-m | -F | (-c | -C) ] []"), + N_("git notes [--ref ] add [-f] [--allow-empty] [--separator=] [-m | -F | (-c | -C) ] []"), N_("git notes [--ref ] copy [-f] "), - N_("git notes [--ref ] append [--allow-empty] [-m | -F | (-c | -C) ] []"), + N_("git notes [--ref ] append [--allow-empty] [--separator=] [-m | -F | (-c | -C) ] []"), N_("git notes [--ref ] edit [--allow-empty] []"), N_("git notes [--ref ] show []"), N_("git notes [--ref ] merge [-v | -q] [-s ] "), @@ -209,37 +210,55 @@ static void write_note_data(struct note_data *d, struct object_id *oid) } } +static void insert_separator(struct strbuf *message, size_t pos) +{ + if (!separator) + strbuf_insertstr(message, pos, "\n"); + else if (separator[strlen(separator) - 1] == '\n') + strbuf_insertstr(message, pos, separator); + else + strbuf_insertf(message, pos, "%s%s", separator, "\n"); +} + +static void parse_messages(struct string_list *messages, struct note_data *d) +{ + size_t i; + for (i = 0; i < messages->nr; i++) { + if (d->buf.len) + insert_separator(&d->buf, d->buf.len); + strbuf_insertstr(&d->buf, d->buf.len, + messages->items[i].string); + strbuf_stripspace(&d->buf, 0); + d->given = 1; + } +} + static int parse_msg_arg(const struct option *opt, const char *arg, int unset) { - struct note_data *d = opt->value; + struct string_list *msg = opt->value; BUG_ON_OPT_NEG(unset); - if (d->buf.len) - strbuf_addch(&d->buf, '\n'); - strbuf_addstr(&d->buf, arg); - strbuf_stripspace(&d->buf, 0); - - d->given = 1; + string_list_append(msg, arg); return 0; } + static int parse_file_arg(const struct option *opt, const char *arg, int unset) { - struct note_data *d = opt->value; + struct string_list *msg = opt->value; + struct strbuf buf = STRBUF_INIT; BUG_ON_OPT_NEG(unset); - if (d->buf.len) - strbuf_addch(&d->buf, '\n'); if (!strcmp(arg, "-")) { - if (strbuf_read(&d->buf, 0, 1024) < 0) + if (strbuf_read(&buf, 0, 1024) < 0) die_errno(_("cannot read '%s'"), arg); - } else if (strbuf_read_file(&d->buf, arg, 1024) < 0) + } else if (strbuf_read_file(&buf, arg, 1024) < 0) die_errno(_("could not open or read '%s'"), arg); - strbuf_stripspace(&d->buf, 0); - d->given = 1; + string_list_append(msg, buf.buf); + strbuf_release(&buf); return 0; } @@ -402,11 +421,12 @@ static int add(int argc, const char **argv, const char *prefix) struct object_id object, new_note; const struct object_id *note; struct note_data d = { .buf = STRBUF_INIT }; + struct string_list messages = STRING_LIST_INIT_DUP; struct option options[] = { - OPT_CALLBACK_F('m', "message", &d, N_("message"), + OPT_CALLBACK_F('m', "message", &messages, N_("message"), N_("note contents as a string"), PARSE_OPT_NONEG, parse_msg_arg), - OPT_CALLBACK_F('F', "file", &d, N_("file"), + OPT_CALLBACK_F('F', "file", &messages, N_("file"), N_("note contents in a file"), PARSE_OPT_NONEG, parse_file_arg), OPT_CALLBACK_F('c', "reedit-message", &d, N_("object"), @@ -418,6 +438,8 @@ static int add(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "allow-empty", &allow_empty, N_("allow storing empty note")), OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE), + OPT_STRING(0, "separator", &separator, N_("separator"), + N_("insert between paragraphs")), OPT_END() }; @@ -429,6 +451,7 @@ static int add(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_add_usage, options); } + parse_messages(&messages, &d); object_ref = argc > 1 ? argv[1] : "HEAD"; if (get_oid(object_ref, &object)) @@ -568,11 +591,12 @@ static int append_edit(int argc, const char **argv, const char *prefix) char *logmsg; const char * const *usage; struct note_data d = { .buf = STRBUF_INIT }; + struct string_list messages = STRING_LIST_INIT_DUP; struct option options[] = { - OPT_CALLBACK_F('m', "message", &d, N_("message"), - N_("note contents as a string"), PARSE_OPT_NONEG, + OPT_CALLBACK_F('m', "message", &messages, N_("message"), + N_("note contents as a string"), PARSE_OPT_NONEG, parse_msg_arg), - OPT_CALLBACK_F('F', "file", &d, N_("file"), + OPT_CALLBACK_F('F', "file", &messages, N_("file"), N_("note contents in a file"), PARSE_OPT_NONEG, parse_file_arg), OPT_CALLBACK_F('c', "reedit-message", &d, N_("object"), @@ -583,6 +607,8 @@ static int append_edit(int argc, const char **argv, const char *prefix) parse_reuse_arg), OPT_BOOL(0, "allow-empty", &allow_empty, N_("allow storing empty note")), + OPT_STRING(0, "separator", &separator, N_("separator"), + N_("insert between paragraphs")), OPT_END() }; int edit = !strcmp(argv[0], "edit"); @@ -596,6 +622,8 @@ static int append_edit(int argc, const char **argv, const char *prefix) usage_with_options(usage, options); } + parse_messages(&messages, &d); + if (d.given && edit) fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated " "for the 'edit' subcommand.\n" @@ -618,7 +646,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) char *prev_buf = read_object_file(note, &type, &size); if (d.buf.len && prev_buf && size) - strbuf_insertstr(&d.buf, 0, "\n"); + insert_separator(&d.buf, 0); if (prev_buf && size) strbuf_insert(&d.buf, 0, prev_buf, size); free(prev_buf); diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 3288aaec..c2c09f32 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -362,6 +362,7 @@ test_expect_success 'do not create empty note with -m ""' ' ' test_expect_success 'create note with combination of -m and -F' ' + test_when_finished git notes remove HEAD && cat >expect-combine_m_and_F <<-EOF && foo @@ -380,6 +381,26 @@ test_expect_success 'create note with combination of -m and -F' ' test_cmp expect-combine_m_and_F actual ' +test_expect_success 'create note with combination of -m and -F and --separator' ' + cat >expect-combine_m_and_F <<-\EOF && + foo + ------- + xyzzy + ------- + bar + ------- + zyxxy + ------- + baz + EOF + echo "xyzzy" >note_a && + echo "zyxxy" >note_b && + git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" --separator "-------" && + git notes show >actual && + test_cmp expect-combine_m_and_F actual + +' + test_expect_success 'remove note with "git notes remove"' ' git notes remove HEAD^ && git notes remove && @@ -521,6 +542,85 @@ test_expect_success 'listing non-existing notes fails' ' test_must_be_empty actual ' +test_expect_success 'append: specify an empty separator' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator with line break' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------$LF" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator without line break' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator with multiple messages' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + ------- + notes-3 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------" -m "notes-2" -m "notes-3" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note with combination of -m and -F and --separator' ' + test_when_finished git notes remove HEAD && + cat >expect-combine_m_and_F <<-\EOF && + m-notes-1 + ------- + f-notes-1 + ------- + m-notes-2 + ------- + f-notes-2 + ------- + m-notes-3 + EOF + + echo "f-notes-1" >note_a && + echo "f-notes-2" >note_b && + git notes append -m "m-notes-1" -F note_a -m "m-notes-2" -F note_b -m "m-notes-3" --separator "-------" && + git notes show >actual && + test_cmp expect-combine_m_and_F actual +' + test_expect_success 'append to existing note with "git notes append"' ' cat >expect <<-EOF && Initial set of notes