From patchwork Wed Jan 31 01:22:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538470 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 736D64C65 for ; Wed, 31 Jan 2024 01:22:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664151; cv=none; b=MgmZrfbrOHcyD2cEjrJvqoJwKwwQfSm5NzRS8l65A3wqM2r5Ry+TFRjUAPn7cn3K+GwjG8Qr49IuXwcuM8ZS8sXkZRgewxQI0527/yAOqpyD4Z3IyPUV620bl/vN1DLeg2J+iPK8Oiq+f77CmG7ksuO30kQsIQfAZtoVg94Tma0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664151; c=relaxed/simple; bh=41r7PyiCZ1fDLegsVKVWLPkEUtwrHbG/GjkW2IVO+wI=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=evlBEjJMwNtL9GhmIfTt2FYg5JlIkIgJbTIi8+TFT0kGShmzj+1HPZZ7pEYSg83iCJeRvwKZy5AJ5KOGxd7+Koss17xBuOCLYLnmBJiS0zYGQJ1dw8F+3KaQD7FS8a21ylcZldrWN1DuSDGBNGpL5KAX5L7H8R4apidiWNDk61c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=T5jEGBTo; arc=none smtp.client-ip=209.85.128.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="T5jEGBTo" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-40e8fec0968so52122775e9.1 for ; Tue, 30 Jan 2024 17:22:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664147; x=1707268947; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=CDdnOUpJoMEuaedPN4FKCmqtCLWzz2GOErCRujlaI1M=; b=T5jEGBTofIfQY12EFlxSwB3QycxHacGxmIdaH2e0yIb4+21cG6+jBXDtyN23t7S0Z1 gWBOcwWWlB4Y3xOjBFRN/nIV3RNHi+00w6eH4xS2V2pYvFoZVhgNn7k1lM1aW4gc4+ZA Mq0uSzzgttwND2XaX8QxVKPJFBMlQngZio5W7/Ya9xGFgzUP3LJ7HwxIfRRHJ6qPEp1h GW+hGMNxxqEvn9oAYAQEAvhPGtiehwXX3wFOkzIORPluR3lsiGCEn/EcLAWDhcRBiGUh 6JBlK1qlLBz3/mxVEa0RXb5cBYXJSHRO9zvK81nxYiat7k7CVLuzWEUVXBpvqB9m8XY1 5e2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664147; x=1707268947; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CDdnOUpJoMEuaedPN4FKCmqtCLWzz2GOErCRujlaI1M=; b=P7MydjExSAGt3Obfs4nTqVoiyD21nNbCkCF+EHh/Nx+hkOAQ2ICY7fIkJ7dO0C6DUd YVgzI7Lo6Nz+Q4DruYxAkrdfrefTUwHBE3UUxdRhtYicVc6FopWHs+48A9dnu99AIQi9 Rq/Of+Y74RW4eYwFPRYeLgns5G8U5g/pjf8P9TrWj2Xyoedt5sS0wX4fWyvCzIammmA7 /etkXvfpIu4ccSW9BlDmsL3okROyhvPdFPAKScjH7xBiY9CGX/mcVN5DrV7rYdjbBrh0 NiuS3AzzUPFH+3lDA+nb2eIvbhtPZcaKCWqA+QPB6+ocP+ZtQ8NV0SPR8x4CyiJII3dw ygLg== X-Gm-Message-State: AOJu0YwYos+leQ1EypQQ1fN5ikW/p+ma/8IC//Bt746fjWDJ1tjAXWCY Ef2tIuBtSVG7PkGyQc0RKIcFlLGHwPnf2aDt5xgjxLkjKf9M97W1Yb06WZF1 X-Google-Smtp-Source: AGHT+IHlSXExND+Nw1c2uvLr7q3LHWCrATIes/3P3cqMPy3IxU/vPxZN9YElDQtbMtgGJUc9wWAf6g== X-Received: by 2002:a05:600c:558a:b0:40f:5c3a:bbb0 with SMTP id jp10-20020a05600c558a00b0040f5c3abbb0mr121821wmb.23.1706664147518; Tue, 30 Jan 2024 17:22:27 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id cx16-20020a056000093000b00337d5cd0d8asm11950585wrb.90.2024.01.30.17.22.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:27 -0800 (PST) Message-ID: <72cc12a306660dde0a09c042160df20b624f785a.1706664145.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:15 +0000 Subject: [PATCH v3 01/10] trailer: prepare to expose functions as part of API Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver In the next patch, we will move "process_trailers" from trailer.c to builtin/interpret-trailers.c. That move will necessitate the growth of the trailer.h API, forcing us to expose some additional functions in trailer.h. Rename relevant functions so that they include the term "trailer" in their name, so that clients of the API will be able to easily identify them by their "trailer" moniker, just like all the other functions already exposed by trailer.h. Take the opportunity to start putting trailer processions options (opts) as the first parameter. This will be the pattern going forward in this series. Helped-by: Junio C Hamano Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 4 ++-- trailer.c | 26 +++++++++++++------------- trailer.h | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 033bd1556cf..85a3413baf5 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -132,11 +132,11 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) if (argc) { int i; for (i = 0; i < argc; i++) - process_trailers(argv[i], &opts, &trailers); + interpret_trailers(&opts, &trailers, argv[i]); } else { if (opts.in_place) die(_("no input file given for in-place editing")); - process_trailers(NULL, &opts, &trailers); + interpret_trailers(&opts, &trailers, NULL); } new_trailers_clear(&trailers); diff --git a/trailer.c b/trailer.c index 3a0710a4583..66b6660f5a4 100644 --- a/trailer.c +++ b/trailer.c @@ -163,12 +163,12 @@ static void print_tok_val(FILE *outfile, const char *tok, const char *val) fprintf(outfile, "%s%c %s\n", tok, separators[0], val); } -static void print_all(FILE *outfile, struct list_head *head, - const struct process_trailer_options *opts) +static void format_trailers(const struct process_trailer_options *opts, + struct list_head *trailers, FILE *outfile) { struct list_head *pos; struct trailer_item *item; - list_for_each(pos, head) { + list_for_each(pos, trailers) { item = list_entry(pos, struct trailer_item, list); if ((!opts->trim_empty || strlen(item->value) > 0) && (!opts->only_trailers || item->token)) @@ -589,7 +589,7 @@ static int git_trailer_config(const char *conf_key, const char *value, return 0; } -static void ensure_configured(void) +static void trailer_config_init(void) { if (configured) return; @@ -1035,10 +1035,10 @@ static void parse_trailers(struct trailer_info *info, } } -static void free_all(struct list_head *head) +static void free_trailers(struct list_head *trailers) { struct list_head *pos, *p; - list_for_each_safe(pos, p, head) { + list_for_each_safe(pos, p, trailers) { list_del(pos); free_trailer_item(list_entry(pos, struct trailer_item, list)); } @@ -1075,16 +1075,16 @@ static FILE *create_in_place_tempfile(const char *file) return outfile; } -void process_trailers(const char *file, - const struct process_trailer_options *opts, - struct list_head *new_trailer_head) +void interpret_trailers(const struct process_trailer_options *opts, + struct list_head *new_trailer_head, + const char *file) { LIST_HEAD(head); struct strbuf sb = STRBUF_INIT; struct trailer_info info; FILE *outfile = stdout; - ensure_configured(); + trailer_config_init(); read_input_file(&sb, file); @@ -1110,9 +1110,9 @@ void process_trailers(const char *file, process_trailers_lists(&head, &arg_head); } - print_all(outfile, &head, opts); + format_trailers(opts, &head, outfile); - free_all(&head); + free_trailers(&head); trailer_info_release(&info); /* Print the lines after the trailers as is */ @@ -1135,7 +1135,7 @@ void trailer_info_get(struct trailer_info *info, const char *str, size_t nr = 0, alloc = 0; char **last = NULL; - ensure_configured(); + trailer_config_init(); end_of_log_message = find_end_of_log_message(str, opts->no_divider); trailer_block_start = find_trailer_block_start(str, end_of_log_message); diff --git a/trailer.h b/trailer.h index 1644cd05f60..37033e631a1 100644 --- a/trailer.h +++ b/trailer.h @@ -81,9 +81,9 @@ struct process_trailer_options { #define PROCESS_TRAILER_OPTIONS_INIT {0} -void process_trailers(const char *file, - const struct process_trailer_options *opts, - struct list_head *new_trailer_head); +void interpret_trailers(const struct process_trailer_options *opts, + struct list_head *new_trailer_head, + const char *file); void trailer_info_get(struct trailer_info *info, const char *str, const struct process_trailer_options *opts); From patchwork Wed Jan 31 01:22:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538472 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4FD24C80 for ; Wed, 31 Jan 2024 01:22:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664152; cv=none; b=Gynvxm6qB6PxuxwzGgyOIt71mfM0g+XY5obgnoEcQlaCN17prSjjfSkvZft6Wc7qXN6lBXfbJubFJyl4UZs0N+YjkY9hIh7frO/sW+YcmdZsPxc4tj2CbKTOr4c4WDhkG//gdsY4wwjC41FTz7M2+TnjdNRwemWE9xVsIAAmmNA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664152; c=relaxed/simple; bh=fMCXjUdyuhLJ4Gc+7eaxYHB0c9IDPxQolPg/NHgAE+U=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=XTBrucfCHQK2MA/bHnly4RdMfRDjYd8gqXC17fw1rmOduMMFtREhbgspOG9PXSfGCUXvF1IpZBnCVwO8VsZCYOL52wNUaL0BdRosGpqC0Ar+D30glzVm1XFh179QIyllH9FvEtLZlw/TVHUNQ6QRtTI3RB0M6D0G3xHkFQxwADc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=P2IPT1aG; arc=none smtp.client-ip=209.85.221.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="P2IPT1aG" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-33ae3cc8a70so2626313f8f.0 for ; Tue, 30 Jan 2024 17:22:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664148; x=1707268948; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=NpojQAaKlGmHiZEzjwkMhzKZt4+nX45Mkg/XBEC8eJM=; b=P2IPT1aGGV0j1fS0GOPLVAFpPZgWOnEPA2cmYhH/QAFsAZB1y3RYwkHdyOG6i7ofgf /9xRTUQk/BpexglG8FZBSgROZuaIyAzg0N7RJryXM6BAkW7Wul/BpQcn+ooSEUKjWrB0 YAyd2CvL2MnKWnsJGq7yKEUPamXvSzQj7E/KTE9kqy67znmEcc6AVC1IVcLS4ZRyqR/4 oQ+RI4U2WzkWo0TpUUGdk6DLUJzSfC8BPD/f1RqOh2RmA7lD1XUSfgXOLQ5Rl4dv7L3Z ZmJ91rPhID3QDRi89RG2z7tFtWgMT88Ln2ttkFqcsOpFieDwIWBPz4hW01J3U4YI3H3q aCOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664148; x=1707268948; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NpojQAaKlGmHiZEzjwkMhzKZt4+nX45Mkg/XBEC8eJM=; b=hTiJh/ufygTnHRdjUl5hh9GdiPZMDYZ6CPkxQafk8nE/ANpmHvkHLpgdQcvQbyna7y 2ob5FTSybk6VX0An619+VYQdtsGhBcsxs/t5vrmerKqBeOU/bvT9TyiQ7DY3rIO+F/A2 sLLHNIwaG9vmpgdoOvm3wvTRmjbSKHfKKT3hZAfmvqLQ0a2jpwLPwAvxFCqOKe5YQVqN e7lziq8xKwKnUeqPptgeitUXxJHYGE8G5jkWhccGmboWe/BxHyomFSzWCCVs7C8sai+V qvbL4LVZkzjHy0JiFtgoTrCclBugv/4cMlb+w52yY7WPYz7wlje/w6bNR7WmVcXu02C6 0aVg== X-Gm-Message-State: AOJu0Yy0xTYHuLIiiK5I5ocRPBMX8QVg4NAur8pidoQOY5GDCC9KRpOT Zqfl041jy1yketx74xUZlxH/PNJK+dNwDSnkGTMFvu5SYzJq1bXmBQdCBmf9 X-Google-Smtp-Source: AGHT+IEGDL1dHyJRcXB8SxQ1QM9KCZXO/lMmLhr9dzbr9w4FMnadkwL1ufZsmqU7tM+SCxZlnpcEBQ== X-Received: by 2002:adf:ec82:0:b0:33a:f1e7:f193 with SMTP id z2-20020adfec82000000b0033af1e7f193mr110895wrn.56.1706664148250; Tue, 30 Jan 2024 17:22:28 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id bw3-20020a0560001f8300b0033b00fe6e96sm692929wrb.14.2024.01.30.17.22.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:27 -0800 (PST) Message-ID: In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:16 +0000 Subject: [PATCH v3 02/10] trailer: move interpret_trailers() to interpret-trailers.c Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver The interpret-trailers.c builtin is the only place we need to call interpret_trailers(), so move its definition there. Delete the corresponding declaration from trailer.h, which then forces us to expose the working innards of that function. This enriches trailer.h with a more granular API, which can then be unit-tested in the future (because interpret_trailers() by itself does too many things to be able to be easily unit-tested). Take this opportunity to demote some file-handling functions out of the trailer API implementation, as these have nothing to do with trailers. Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 94 +++++++++++++++++++++++++++ trailer.c | 120 ++++------------------------------- trailer.h | 20 +++++- 3 files changed, 124 insertions(+), 110 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 85a3413baf5..8556acde4aa 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -9,6 +9,7 @@ #include "gettext.h" #include "parse-options.h" #include "string-list.h" +#include "tempfile.h" #include "trailer.h" #include "config.h" @@ -91,6 +92,99 @@ static int parse_opt_parse(const struct option *opt, const char *arg, return 0; } +static struct tempfile *trailers_tempfile; + +static FILE *create_in_place_tempfile(const char *file) +{ + struct stat st; + struct strbuf filename_template = STRBUF_INIT; + const char *tail; + FILE *outfile; + + if (stat(file, &st)) + die_errno(_("could not stat %s"), file); + if (!S_ISREG(st.st_mode)) + die(_("file %s is not a regular file"), file); + if (!(st.st_mode & S_IWUSR)) + die(_("file %s is not writable by user"), file); + + /* Create temporary file in the same directory as the original */ + tail = strrchr(file, '/'); + if (tail) + strbuf_add(&filename_template, file, tail - file + 1); + strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX"); + + trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode); + strbuf_release(&filename_template); + outfile = fdopen_tempfile(trailers_tempfile, "w"); + if (!outfile) + die_errno(_("could not open temporary file")); + + return outfile; +} + +static void read_input_file(struct strbuf *sb, const char *file) +{ + if (file) { + if (strbuf_read_file(sb, file, 0) < 0) + die_errno(_("could not read input file '%s'"), file); + } else { + if (strbuf_read(sb, fileno(stdin), 0) < 0) + die_errno(_("could not read from stdin")); + } +} + +static void interpret_trailers(const struct process_trailer_options *opts, + struct list_head *new_trailer_head, + const char *file) +{ + LIST_HEAD(head); + struct strbuf sb = STRBUF_INIT; + struct trailer_info info; + FILE *outfile = stdout; + + trailer_config_init(); + + read_input_file(&sb, file); + + if (opts->in_place) + outfile = create_in_place_tempfile(file); + + parse_trailers(opts, &info, sb.buf, &head); + + /* Print the lines before the trailers */ + if (!opts->only_trailers) + fwrite(sb.buf, 1, info.trailer_block_start, outfile); + + if (!opts->only_trailers && !info.blank_line_before_trailer) + fprintf(outfile, "\n"); + + + if (!opts->only_input) { + LIST_HEAD(config_head); + LIST_HEAD(arg_head); + parse_trailers_from_config(&config_head); + parse_trailers_from_command_line_args(&arg_head, new_trailer_head); + list_splice(&config_head, &arg_head); + process_trailers_lists(&head, &arg_head); + } + + format_trailers(opts, &head, outfile); + + free_trailers(&head); + trailer_info_release(&info); + + /* Print the lines after the trailers as is */ + if (!opts->only_trailers) + fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile); + + if (opts->in_place) + if (rename_tempfile(&trailers_tempfile, file)) + die_errno(_("could not rename temporary file to %s"), file); + + strbuf_release(&sb); +} + int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; diff --git a/trailer.c b/trailer.c index 66b6660f5a4..d3899195876 100644 --- a/trailer.c +++ b/trailer.c @@ -5,7 +5,6 @@ #include "string-list.h" #include "run-command.h" #include "commit.h" -#include "tempfile.h" #include "trailer.h" #include "list.h" /* @@ -163,8 +162,8 @@ static void print_tok_val(FILE *outfile, const char *tok, const char *val) fprintf(outfile, "%s%c %s\n", tok, separators[0], val); } -static void format_trailers(const struct process_trailer_options *opts, - struct list_head *trailers, FILE *outfile) +void format_trailers(const struct process_trailer_options *opts, + struct list_head *trailers, FILE *outfile) { struct list_head *pos; struct trailer_item *item; @@ -366,8 +365,8 @@ static int find_same_and_apply_arg(struct list_head *head, return 0; } -static void process_trailers_lists(struct list_head *head, - struct list_head *arg_head) +void process_trailers_lists(struct list_head *head, + struct list_head *arg_head) { struct list_head *pos, *p; struct arg_item *arg_tok; @@ -589,7 +588,7 @@ static int git_trailer_config(const char *conf_key, const char *value, return 0; } -static void trailer_config_init(void) +void trailer_config_init(void) { if (configured) return; @@ -719,7 +718,7 @@ static void add_arg_item(struct list_head *arg_head, char *tok, char *val, list_add_tail(&new_item->list, arg_head); } -static void parse_trailers_from_config(struct list_head *config_head) +void parse_trailers_from_config(struct list_head *config_head) { struct arg_item *item; struct list_head *pos; @@ -735,8 +734,8 @@ static void parse_trailers_from_config(struct list_head *config_head) } } -static void parse_trailers_from_command_line_args(struct list_head *arg_head, - struct list_head *new_trailer_head) +void parse_trailers_from_command_line_args(struct list_head *arg_head, + struct list_head *new_trailer_head) { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; @@ -775,17 +774,6 @@ static void parse_trailers_from_command_line_args(struct list_head *arg_head, free(cl_separators); } -static void read_input_file(struct strbuf *sb, const char *file) -{ - if (file) { - if (strbuf_read_file(sb, file, 0) < 0) - die_errno(_("could not read input file '%s'"), file); - } else { - if (strbuf_read(sb, fileno(stdin), 0) < 0) - die_errno(_("could not read from stdin")); - } -} - static const char *next_line(const char *str) { const char *nl = strchrnul(str, '\n'); @@ -1000,10 +988,10 @@ static void unfold_value(struct strbuf *val) * Parse trailers in "str", populating the trailer info and "head" * linked list structure. */ -static void parse_trailers(struct trailer_info *info, - const char *str, - struct list_head *head, - const struct process_trailer_options *opts) +void parse_trailers(const struct process_trailer_options *opts, + struct trailer_info *info, + const char *str, + struct list_head *head) { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; @@ -1035,7 +1023,7 @@ static void parse_trailers(struct trailer_info *info, } } -static void free_trailers(struct list_head *trailers) +void free_trailers(struct list_head *trailers) { struct list_head *pos, *p; list_for_each_safe(pos, p, trailers) { @@ -1044,88 +1032,6 @@ static void free_trailers(struct list_head *trailers) } } -static struct tempfile *trailers_tempfile; - -static FILE *create_in_place_tempfile(const char *file) -{ - struct stat st; - struct strbuf filename_template = STRBUF_INIT; - const char *tail; - FILE *outfile; - - if (stat(file, &st)) - die_errno(_("could not stat %s"), file); - if (!S_ISREG(st.st_mode)) - die(_("file %s is not a regular file"), file); - if (!(st.st_mode & S_IWUSR)) - die(_("file %s is not writable by user"), file); - - /* Create temporary file in the same directory as the original */ - tail = strrchr(file, '/'); - if (tail) - strbuf_add(&filename_template, file, tail - file + 1); - strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX"); - - trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode); - strbuf_release(&filename_template); - outfile = fdopen_tempfile(trailers_tempfile, "w"); - if (!outfile) - die_errno(_("could not open temporary file")); - - return outfile; -} - -void interpret_trailers(const struct process_trailer_options *opts, - struct list_head *new_trailer_head, - const char *file) -{ - LIST_HEAD(head); - struct strbuf sb = STRBUF_INIT; - struct trailer_info info; - FILE *outfile = stdout; - - trailer_config_init(); - - read_input_file(&sb, file); - - if (opts->in_place) - outfile = create_in_place_tempfile(file); - - parse_trailers(&info, sb.buf, &head, opts); - - /* Print the lines before the trailers */ - if (!opts->only_trailers) - fwrite(sb.buf, 1, info.trailer_block_start, outfile); - - if (!opts->only_trailers && !info.blank_line_before_trailer) - fprintf(outfile, "\n"); - - - if (!opts->only_input) { - LIST_HEAD(config_head); - LIST_HEAD(arg_head); - parse_trailers_from_config(&config_head); - parse_trailers_from_command_line_args(&arg_head, new_trailer_head); - list_splice(&config_head, &arg_head); - process_trailers_lists(&head, &arg_head); - } - - format_trailers(opts, &head, outfile); - - free_trailers(&head); - trailer_info_release(&info); - - /* Print the lines after the trailers as is */ - if (!opts->only_trailers) - fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile); - - if (opts->in_place) - if (rename_tempfile(&trailers_tempfile, file)) - die_errno(_("could not rename temporary file to %s"), file); - - strbuf_release(&sb); -} - void trailer_info_get(struct trailer_info *info, const char *str, const struct process_trailer_options *opts) { diff --git a/trailer.h b/trailer.h index 37033e631a1..ca701c04f3b 100644 --- a/trailer.h +++ b/trailer.h @@ -81,15 +81,29 @@ struct process_trailer_options { #define PROCESS_TRAILER_OPTIONS_INIT {0} -void interpret_trailers(const struct process_trailer_options *opts, - struct list_head *new_trailer_head, - const char *file); +void parse_trailers_from_config(struct list_head *config_head); + +void parse_trailers_from_command_line_args(struct list_head *arg_head, + struct list_head *new_trailer_head); + +void process_trailers_lists(struct list_head *head, + struct list_head *arg_head); + +void parse_trailers(const struct process_trailer_options *opts, + struct trailer_info *info, + const char *str, + struct list_head *head); void trailer_info_get(struct trailer_info *info, const char *str, const struct process_trailer_options *opts); void trailer_info_release(struct trailer_info *info); +void trailer_config_init(void); +void format_trailers(const struct process_trailer_options *opts, + struct list_head *trailers, FILE *outfile); +void free_trailers(struct list_head *); + /* * Format the trailers from the commit msg "msg" into the strbuf "out". * Note two caveats about "opts": From patchwork Wed Jan 31 01:22:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538473 Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 975094C8B for ; Wed, 31 Jan 2024 01:22:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664153; cv=none; b=GUPoMY/AJpqikqjJ/t5p0iMhDuLfE5QFs47nmibIgS2NfpN75QAmzg5H3Ym0vyK2nJbDkal7BcOzeT4T/0EBJuxMy6JKmgLRx2cbl7gNYp+jveluEz8knptrXChaH5h8IpFpa0/Sh41jOY/p0fN5yBX66tKrbEOClDMQu1SvUN4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664153; c=relaxed/simple; bh=qD11dIUtmh9kRSMtA+SMDwCYtB3P4MWKWYsRkERDAuE=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=K7BnU3FubZ/uJ+2EZKwxDMITArQXfm9K3U1hfVU46rwa6AAHeDJvI0s3/sWoDzpGpykwha/5Nnk5rHslRlKB9FkvtkvoQE2wdQTvJ3Bun7Rh4H0BWE553Wv5DjOxDRy/E4yWQ67XAQHrUy8ESV1yiqISBNrojiS9e7Xk3vtglds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TF2aEMQn; arc=none smtp.client-ip=209.85.221.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TF2aEMQn" Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-33ae3be1c37so197174f8f.0 for ; Tue, 30 Jan 2024 17:22:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664149; x=1707268949; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=xnHHQoR9/DDo6ct23yHBud4gJU5mZOnRADHbnIfxa4g=; b=TF2aEMQnVjsqeE+UHD9kLjZlwfrskXVA5QQQKYufwsO2bztRaSwKa0FIEryiacBgZc Tx5iF/E0wPOVN8BlhqeePvyz1sZyonQnos5Ojh4gAFAcZK/u32Ws92/h7ZrYls/EE95h lvDrRSwTSJBUvvVxPY72dGnr2Q8tWUuqxYBiIZWTEpnZQP/TvyEWREdvn+pXlpx7grqp glDL/VC+A5lEMJpNIJLRBr8QsXZi8LS0himhKecu821R35fqnZO7m1X9EhNT2UYsK5IZ Lnbqxp1MOZYEsJD6Wy93NdeiK2N1GmrOXmivSVkYgZV9vckdbBrtPSOYEBXKC3HkNtWT AOMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664149; x=1707268949; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xnHHQoR9/DDo6ct23yHBud4gJU5mZOnRADHbnIfxa4g=; b=WAEnd2FiuPyqKikfnzGbFgEOBKGE+tJQqXC1sZtiZGx5hppZpTW26riTKt7/Ji7ebO u2ENG8kTSDe8mO92KRlxhxxNiorXKgFNMCnJcf8rUeeDAz6Vnlp57Y/HSsv5UpOCsc/x pIjK/sgCn1qyJ9IqhpSrCHG6TK9piLLsjXLAM4Jww87UKcfab2YCMUJHXjcYSyjupHtr WW8R3UWe8ANP7qNLVbTl87Kw9BoWRwsEuCmKQi0Tg4zxNN6EYUU3weEyBK951l3WrV2H t2G5L+ZLS+RZ/h4i+eddFwgfAtuIPprY40AAcEXoCyxm1PTOxm6zyga2mWVyCSy44g4S OjdQ== X-Gm-Message-State: AOJu0YzElp20byoXkBljntiKIPhr0U3y5kTplcve+sDyJHeMOBaIQOdn hhrAsOMWWtz1qsbed4ZoHnCeNtj2Y70SH7/EaOyduVIrIjfi4QBLgd8TaTlP X-Google-Smtp-Source: AGHT+IHwxtyHY/ONZ8YXDkHbIYTbbJwMP5Qye/UetWe7psOGoqjyLxa1awYBFLaPR4wImjXQIsur1g== X-Received: by 2002:a5d:484c:0:b0:336:58e8:d444 with SMTP id n12-20020a5d484c000000b0033658e8d444mr2832820wrs.30.1706664149542; Tue, 30 Jan 2024 17:22:29 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id ay12-20020a5d6f0c000000b0033ad47d7b86sm12075982wrb.27.2024.01.30.17.22.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:28 -0800 (PST) Message-ID: <5c7a2354df0f4a29841f9ab8294ead0e1c3b9cf5.1706664145.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:17 +0000 Subject: [PATCH v3 03/10] trailer: unify trailer formatting machinery Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver Currently have two functions for formatting trailers exposed in trailer.h: void format_trailers(FILE *outfile, struct list_head *head, const struct process_trailer_options *opts); void format_trailers_from_commit(struct strbuf *out, const char *msg, const struct process_trailer_options *opts); and previously these functions, although similar enough (even taking the same process_trailer_options struct pointer), did not build on each other. Make format_trailers_from_commit() rely on format_trailers(). Teach format_trailers() to process trailers with the additional process_trailer_options fields like opts->key_only which is only used by format_trailers_from_commit() and not builtin/interpret-trailers.c. While we're at it, reorder parameters to put the trailer processing options first, and the out parameter (strbuf we write into) at the end. This unification will allow us to delete the format_trailer_info() and print_tok_val() functions in the next patch. They are not deleted here in order to keep the diff small. Helped-by: Junio C Hamano Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 6 +- pretty.c | 2 +- ref-filter.c | 2 +- trailer.c | 176 +++++++++++++++++------------------ trailer.h | 19 ++-- 5 files changed, 98 insertions(+), 107 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 8556acde4aa..5352ee65bd1 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -140,6 +140,7 @@ static void interpret_trailers(const struct process_trailer_options *opts, { LIST_HEAD(head); struct strbuf sb = STRBUF_INIT; + struct strbuf trailer_block = STRBUF_INIT; struct trailer_info info; FILE *outfile = stdout; @@ -169,7 +170,10 @@ static void interpret_trailers(const struct process_trailer_options *opts, process_trailers_lists(&head, &arg_head); } - format_trailers(opts, &head, outfile); + /* Print trailer block. */ + format_trailers(opts, &head, &trailer_block); + fwrite(trailer_block.buf, 1, trailer_block.len, outfile); + strbuf_release(&trailer_block); free_trailers(&head); trailer_info_release(&info); diff --git a/pretty.c b/pretty.c index cf964b060cd..bdbed4295aa 100644 --- a/pretty.c +++ b/pretty.c @@ -1759,7 +1759,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ goto trailer_out; } if (*arg == ')') { - format_trailers_from_commit(sb, msg + c->subject_off, &opts); + format_trailers_from_commit(&opts, msg + c->subject_off, sb); ret = arg - placeholder + 1; } trailer_out: diff --git a/ref-filter.c b/ref-filter.c index 35b989e1dfe..d358953b0ce 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -1985,7 +1985,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp struct strbuf s = STRBUF_INIT; /* Format the trailer info according to the trailer_opts given */ - format_trailers_from_commit(&s, subpos, &atom->u.contents.trailer_opts); + format_trailers_from_commit(&atom->u.contents.trailer_opts, subpos, &s); v->s = strbuf_detach(&s, NULL); } else if (atom->u.contents.option == C_BARE) diff --git a/trailer.c b/trailer.c index d3899195876..71ea2bb67f8 100644 --- a/trailer.c +++ b/trailer.c @@ -144,37 +144,6 @@ static char last_non_space_char(const char *s) return '\0'; } -static void print_tok_val(FILE *outfile, const char *tok, const char *val) -{ - char c; - - if (!tok) { - fprintf(outfile, "%s\n", val); - return; - } - - c = last_non_space_char(tok); - if (!c) - return; - if (strchr(separators, c)) - fprintf(outfile, "%s%s\n", tok, val); - else - fprintf(outfile, "%s%c %s\n", tok, separators[0], val); -} - -void format_trailers(const struct process_trailer_options *opts, - struct list_head *trailers, FILE *outfile) -{ - struct list_head *pos; - struct trailer_item *item; - list_for_each(pos, trailers) { - item = list_entry(pos, struct trailer_item, list); - if ((!opts->trim_empty || strlen(item->value) > 0) && - (!opts->only_trailers || item->token)) - print_tok_val(outfile, item->token, item->value); - } -} - static struct trailer_item *trailer_from_arg(struct arg_item *arg_tok) { struct trailer_item *new_item = xcalloc(1, sizeof(*new_item)); @@ -984,6 +953,78 @@ static void unfold_value(struct strbuf *val) strbuf_release(&out); } +void format_trailers(const struct process_trailer_options *opts, + struct list_head *trailers, + struct strbuf *out) +{ + struct list_head *pos; + struct trailer_item *item; + int need_separator = 0; + + list_for_each(pos, trailers) { + item = list_entry(pos, struct trailer_item, list); + if (item->token) { + char c; + + struct strbuf tok = STRBUF_INIT; + struct strbuf val = STRBUF_INIT; + strbuf_addstr(&tok, item->token); + strbuf_addstr(&val, item->value); + + /* + * Skip key/value pairs where the value was empty. This + * can happen from trailers specified without a + * separator, like `--trailer "Reviewed-by"` (no + * corresponding value). + */ + if (opts->trim_empty && !strlen(item->value)) + continue; + + if (!opts->filter || opts->filter(&tok, opts->filter_data)) { + if (opts->unfold) + unfold_value(&val); + + if (opts->separator && need_separator) + strbuf_addbuf(out, opts->separator); + if (!opts->value_only) + strbuf_addbuf(out, &tok); + if (!opts->key_only && !opts->value_only) { + if (opts->key_value_separator) + strbuf_addbuf(out, opts->key_value_separator); + else { + c = last_non_space_char(tok.buf); + if (c) { + if (!strchr(separators, c)) + strbuf_addf(out, "%c ", separators[0]); + } + } + } + if (!opts->key_only) + strbuf_addbuf(out, &val); + if (!opts->separator) + strbuf_addch(out, '\n'); + + need_separator = 1; + } + + strbuf_release(&tok); + strbuf_release(&val); + } else if (!opts->only_trailers) { + if (opts->separator && need_separator) { + strbuf_addbuf(out, opts->separator); + } + strbuf_addstr(out, item->value); + if (opts->separator) + strbuf_rtrim(out); + else + strbuf_addch(out, '\n'); + + need_separator = 1; + } + + } +} + /* * Parse trailers in "str", populating the trailer info and "head" * linked list structure. @@ -1083,74 +1124,25 @@ void trailer_info_release(struct trailer_info *info) free(info->trailers); } -static void format_trailer_info(struct strbuf *out, - const struct trailer_info *info, - const char *msg, - const struct process_trailer_options *opts) +void format_trailers_from_commit(const struct process_trailer_options *opts, + const char *msg, + struct strbuf *out) { - size_t origlen = out->len; - size_t i; + LIST_HEAD(head); + struct trailer_info info; + + parse_trailers(opts, &info, msg, &head); /* If we want the whole block untouched, we can take the fast path. */ if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator && !opts->key_only && !opts->value_only && !opts->key_value_separator) { - strbuf_add(out, msg + info->trailer_block_start, - info->trailer_block_end - info->trailer_block_start); - return; - } - - for (i = 0; i < info->trailer_nr; i++) { - char *trailer = info->trailers[i]; - ssize_t separator_pos = find_separator(trailer, separators); - - if (separator_pos >= 1) { - struct strbuf tok = STRBUF_INIT; - struct strbuf val = STRBUF_INIT; - - parse_trailer(&tok, &val, NULL, trailer, separator_pos); - if (!opts->filter || opts->filter(&tok, opts->filter_data)) { - if (opts->unfold) - unfold_value(&val); - - if (opts->separator && out->len != origlen) - strbuf_addbuf(out, opts->separator); - if (!opts->value_only) - strbuf_addbuf(out, &tok); - if (!opts->key_only && !opts->value_only) { - if (opts->key_value_separator) - strbuf_addbuf(out, opts->key_value_separator); - else - strbuf_addstr(out, ": "); - } - if (!opts->key_only) - strbuf_addbuf(out, &val); - if (!opts->separator) - strbuf_addch(out, '\n'); - } - strbuf_release(&tok); - strbuf_release(&val); - - } else if (!opts->only_trailers) { - if (opts->separator && out->len != origlen) { - strbuf_addbuf(out, opts->separator); - } - strbuf_addstr(out, trailer); - if (opts->separator) { - strbuf_rtrim(out); - } - } - } - -} - -void format_trailers_from_commit(struct strbuf *out, const char *msg, - const struct process_trailer_options *opts) -{ - struct trailer_info info; + strbuf_add(out, msg + info.trailer_block_start, + info.trailer_block_end - info.trailer_block_start); + } else + format_trailers(opts, &head, out); - trailer_info_get(&info, msg, opts); - format_trailer_info(out, &info, msg, opts); + free_trailers(&head); trailer_info_release(&info); } diff --git a/trailer.h b/trailer.h index ca701c04f3b..244f29fc91f 100644 --- a/trailer.h +++ b/trailer.h @@ -101,22 +101,17 @@ void trailer_info_release(struct trailer_info *info); void trailer_config_init(void); void format_trailers(const struct process_trailer_options *opts, - struct list_head *trailers, FILE *outfile); + struct list_head *trailers, + struct strbuf *out); void free_trailers(struct list_head *); /* - * Format the trailers from the commit msg "msg" into the strbuf "out". - * Note two caveats about "opts": - * - * - this is primarily a helper for pretty.c, and not - * all of the flags are supported. - * - * - this differs from process_trailers slightly in that we always format - * only the trailer block itself, even if the "only_trailers" option is not - * set. + * Convenience function to format the trailers from the commit msg "msg" into + * the strbuf "out". Reuses format_trailers internally. */ -void format_trailers_from_commit(struct strbuf *out, const char *msg, - const struct process_trailer_options *opts); +void format_trailers_from_commit(const struct process_trailer_options *opts, + const char *msg, + struct strbuf *out); /* * An interface for iterating over the trailers found in a particular commit From patchwork Wed Jan 31 01:22:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538474 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2AEC538A for ; Wed, 31 Jan 2024 01:22:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664154; cv=none; b=M6EZvQdqB5ZVsGnN/SwHyHtg/9uiO8qnF1VMQm3qd+hlAX5SXpARR3yEcK1REuF1TxG+PaAU0qcQPOe1Jaxhxn4DhtlgaXIXR4TVMnU2cwCIVHb0D6AB/0oA5Yggqa6Ui0KDu6cepGhIMeZzPxxYIy+f9W9k7IRnwc7KvH/7kvw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664154; c=relaxed/simple; bh=q1YPuIGuy9Tyw9goIgwi43rgcK2T5+A0V2OoozjLGiY=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=KHM5RuGNQiBHUA+vcC07ZWal56yAmmaFhX0/K2Q6aiczbiMZF7IJv3iYl4dgJvwChFmzGPplVpbQbAzMpnlPmq+dOb8ltC5c/b22SqRYE16gfaWTZVFWTWe2SCOfBhnFvYchNKctSw0laT1d6Dm8Pzoz1+mzu53z4muM3ctPoQQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VDv7Cz6P; arc=none smtp.client-ip=209.85.221.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VDv7Cz6P" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-33ae53eb5a8so2164430f8f.3 for ; Tue, 30 Jan 2024 17:22:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664150; x=1707268950; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=0+S8JwqhMBSjfpGulKSpBMHKeVvufhIUPwqrrKVw+os=; b=VDv7Cz6PTCRw4ubZPdgd4siCAcO4QrERZ7QkESuLp85puailUPc4svnf4a3Tjoj2n7 apAYTX8zBkhL+g0GHnMGI+2CzDOG8UmmIeZvJgiVxd7iiraO3afn7eSX8puUdWUISpkz QCdkIfGRRgiIK3Zn51iyNDsEx0+21nTR+S3FSmx7Jh1qnms182/QKhhbSydtpSH9o9pk R3as5/U9UN8PzSNS1OZpyAUdqI4+2PswoYutoeb3G1KvUxJqQsCmdmTR/j7q5HPniB0u yjcOLotWSvuLZ9iaKuRD9Gs1KfOGBYlCz+us3ArY0B5unC7MHMMf+NN/YaQmkmI14SF0 aX9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664150; x=1707268950; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0+S8JwqhMBSjfpGulKSpBMHKeVvufhIUPwqrrKVw+os=; b=pDEmZKsxVLsMSIUC7v8GjML8bG+JV0as4/xTXfdmMLbeCg/Q+WXBjcIZOFb2iZO5oW KyL4LgdPGrdN3Ff3EiHBc4wb8UjyJM6lq4BVu2/5XZUuJNkXFdmtmqZbhROrISLnDChI t4t/9WFF029ak/3g6fd+UaitPIvwLR8kQ6VRpn/M/xUlNy899NTZ3HREi3BXU4fSEstI LKkTnzoDAR2/PlsJBCA2TIGGk5QxziQ5DltzrsNhjAdM8ZQXs9DGYiJctO4bzEki295B ukx79fe66dUvRBfKP4COXSURYcKs/yAVeLUQWddWTmiwfVGqJwf4UgX0cpqF+a0Hwyj0 Jtcw== X-Gm-Message-State: AOJu0YxMugB4x4ek21DcFqoGrwPi0TbDbvgP19G4fxorQslRnqXHmEf+ jUuONxAeKy21WOYGJiBx+g1JLtiZfGeGXKAzxUHJQgv8YH82iP2dgCpe1ans X-Google-Smtp-Source: AGHT+IEsXYzPpPfCfsZkhiesVL7X8C3KUWp4vy4u3ES35GLke1S7z68AOTQg3S5pioAb7YDZhxuV5g== X-Received: by 2002:a5d:4d44:0:b0:33a:e808:31a4 with SMTP id a4-20020a5d4d44000000b0033ae80831a4mr77831wru.55.1706664150350; Tue, 30 Jan 2024 17:22:30 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k14-20020adff28e000000b003392172fd60sm11930404wro.51.2024.01.30.17.22.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:29 -0800 (PST) Message-ID: In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:18 +0000 Subject: [PATCH v3 04/10] sequencer: use the trailer iterator Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver This patch allows for the removal of "trailer_info_get()" from the trailer.h API, which will be in the next patch. Instead of calling "trailer_info_get()", which is a low-level function in the trailers implementation (trailer.c), call trailer_iterator_advance(), which was specifically designed for public consumption in f0939a0eb1 (trailer: add interface for iterating over commit trailers, 2020-09-27). Avoiding "trailer_info_get()" means we don't have to worry about options like "no_divider" (relevant for parsing trailers). We also don't have to check for things like "info.trailer_start == info.trailer_end" to see whether there were any trailers (instead we can just check to see whether the iterator advanced at all). Also, teach the iterator about non-trailer lines, by adding a new field called "raw" to hold both trailer and non-trailer lines. This is necessary because a "trailer block" is a list of trailer lines of at least 25% trailers (see 146245063e (trailer: allow non-trailers in trailer block, 2016-10-21)), such that it may hold non-trailer lines. Signed-off-by: Linus Arver --- builtin/shortlog.c | 7 +++++-- sequencer.c | 35 +++++++++++++++-------------------- trailer.c | 17 +++++++++-------- trailer.h | 13 +++++++++++++ 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 1307ed2b88a..dc8fd5a5532 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -172,7 +172,7 @@ static void insert_records_from_trailers(struct shortlog *log, const char *oneline) { struct trailer_iterator iter; - const char *commit_buffer, *body; + const char *commit_buffer, *body, *value; struct strbuf ident = STRBUF_INIT; if (!log->trailers.nr) @@ -190,7 +190,10 @@ static void insert_records_from_trailers(struct shortlog *log, trailer_iterator_init(&iter, body); while (trailer_iterator_advance(&iter)) { - const char *value = iter.val.buf; + if (!iter.is_trailer) + continue; + + value = iter.val.buf; if (!string_list_has_string(&log->trailers, iter.key.buf)) continue; diff --git a/sequencer.c b/sequencer.c index 3cc88d8a800..bc7c82c5271 100644 --- a/sequencer.c +++ b/sequencer.c @@ -319,37 +319,32 @@ static const char *get_todo_path(const struct replay_opts *opts) static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob, size_t ignore_footer) { - struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; - struct trailer_info info; - size_t i; - int found_sob = 0, found_sob_last = 0; - char saved_char; - - opts.no_divider = 1; + struct trailer_iterator iter; + size_t i = 0, found_sob = 0; + char saved_char = sb->buf[sb->len - ignore_footer]; if (ignore_footer) { - saved_char = sb->buf[sb->len - ignore_footer]; sb->buf[sb->len - ignore_footer] = '\0'; } - trailer_info_get(&info, sb->buf, &opts); + trailer_iterator_init(&iter, sb->buf); + while (trailer_iterator_advance(&iter)) { + i++; + if (sob && + iter.is_trailer && + !strncmp(iter.raw, sob->buf, sob->len)) { + found_sob = i; + } + } + trailer_iterator_release(&iter); if (ignore_footer) sb->buf[sb->len - ignore_footer] = saved_char; - if (info.trailer_block_start == info.trailer_block_end) + if (!i) return 0; - for (i = 0; i < info.trailer_nr; i++) - if (sob && !strncmp(info.trailers[i], sob->buf, sob->len)) { - found_sob = 1; - if (i == info.trailer_nr - 1) - found_sob_last = 1; - } - - trailer_info_release(&info); - - if (found_sob_last) + if (found_sob == i) return 3; if (found_sob) return 2; diff --git a/trailer.c b/trailer.c index 71ea2bb67f8..5bcc9b0006c 100644 --- a/trailer.c +++ b/trailer.c @@ -1158,17 +1158,18 @@ void trailer_iterator_init(struct trailer_iterator *iter, const char *msg) int trailer_iterator_advance(struct trailer_iterator *iter) { - while (iter->internal.cur < iter->internal.info.trailer_nr) { - char *trailer = iter->internal.info.trailers[iter->internal.cur++]; - int separator_pos = find_separator(trailer, separators); - - if (separator_pos < 1) - continue; /* not a real trailer */ - + char *line; + int separator_pos; + if (iter->internal.cur < iter->internal.info.trailer_nr) { + line = iter->internal.info.trailers[iter->internal.cur++]; + separator_pos = find_separator(line, separators); + iter->is_trailer = (separator_pos > 0); + + iter->raw = line; strbuf_reset(&iter->key); strbuf_reset(&iter->val); parse_trailer(&iter->key, &iter->val, NULL, - trailer, separator_pos); + line, separator_pos); unfold_value(&iter->val); return 1; } diff --git a/trailer.h b/trailer.h index 244f29fc91f..a7599067acc 100644 --- a/trailer.h +++ b/trailer.h @@ -127,6 +127,19 @@ struct trailer_iterator { struct strbuf key; struct strbuf val; + /* + * Raw line (e.g., "foo: bar baz") before being parsed as a trailer + * key/val pair as part of a trailer block. A trailer block can be + * either 100% trailer lines, or mixed in with non-trailer lines (in + * which case at least 25% must be trailer lines). + */ + const char *raw; + + /* + * 1 if the raw line was parsed as a trailer line (key/val pair). + */ + int is_trailer; + /* private */ struct { struct trailer_info info; From patchwork Wed Jan 31 01:22:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538475 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC8BE5695 for ; Wed, 31 Jan 2024 01:22:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664156; cv=none; b=hPPS0xCD/6CLdJ/SjPxXtU8XlT2dzxe7yxlL36QX4hbzkyX4i8C+RGKpStWcv1d2XOeD02wXH1JTGdpf8RRbVPSXXQYhXAnLgI+YlTuQoDEi7Ura5/DGse7uq/H+x5szi0dmwj2Lz0qMOl/H1AF7xvjQpDCXP2a6Sc//IzBr/4w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664156; c=relaxed/simple; bh=p4amNcyF7pkYBLRDDVTajQVV95AsrJ2nBoXNm7O2WRQ=; h=Message-ID:In-Reply-To:References:From:Date:Subject:MIME-Version: Content-Type:To:Cc; b=aaIGGIHsaIqBDdpdEiwmczW0o8vG3KZs/cDdnNRtxFMBXMJn0DbuZ6Fi7B5VQMrRoec7qhXModZBnkGa8h820vm/NANP7UUQyDkc/99xf8aIFxeh6ewgQuZ4pihhx8lH5pMeLtzPi2q45BYzHe6JOquLNlH2ONuBgd/FUsIQzO4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=fFLNK1fQ; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fFLNK1fQ" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-40fb44a9520so987505e9.1 for ; Tue, 30 Jan 2024 17:22:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664152; x=1707268952; darn=vger.kernel.org; h=cc:to:fcc:content-transfer-encoding:mime-version:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=MHq0WOMxzcy3aEQgW9T+j55zIJMEXOgbEcNZdI/UviY=; b=fFLNK1fQzXHSz4jAfckzCfCgOOaUODkm9LCMa/U54P1jkud2XmaUl3ZMO6af64r5vc cjhRaZ7kDeOGEySqsrKdvGjeH1Q+ueJd86WpVw3VesQz+kIZcLDv64XqGohVq9YjLM+s seYx5IdwgTRHPk5Qxh+vQkBogrirIHbRLeFnF+SuedHqn8dRTeK1JdsKFbS5r3uiQrwg t23JHrFC3MHXugZ/vLebwsp9BP3wKmZE7jLhh9qCJOHHiwcSDACNF4Ik7oHSLdUhqd38 BbB0/EjhD9QR7I+BhVO61Dc+h/QmmcpK6+sl1kPajqJT3eidccVRCsOPHe/UgMqJgUcj dNjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664152; x=1707268952; h=cc:to:fcc:content-transfer-encoding:mime-version:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MHq0WOMxzcy3aEQgW9T+j55zIJMEXOgbEcNZdI/UviY=; b=ar5QPFSO9gbGsfseNaYvA+PDwRLR/Btu8Qmo7LMtb1sjhJjTQ1gbi1iG642d18/SME CP+bZOsYz3kJakLtbM4AZuBG0rgQ02SQ3y+d2RTLS3ZwuXf5wXSqi7hV4gg2Az1LtS4Z DcDxslDvwlfaZ384c6Yz5Xw1dzgaek3Xm2lqry/tB53z0NP4J5pv55JLPuvzNk7y2g6K 26LFbcygQj0Q7KJ0wTPT5IsDBLxyKHyWPuWBAooI6ZytofVa1kkPDOjUGy8vno0tA/3E N3f++7DbLHlcbi38hrCCXWvZtFX66s4DqeHjAZr7ofdxoGCI7ujgGUfs3ZP04t+/A3ma BJEQ== X-Gm-Message-State: AOJu0Yyg5KgP7bmO5p7X6huTRCcL1sb5R+cyDQ8d6s5/x4YCt8XZn51f bXfnbHU/cxXyJpDFz71bRpKmv2JPyX4knelWaTQyr2uIYrKIzBZyt40iSKym X-Google-Smtp-Source: AGHT+IFHlNb2HqepF91KP7IZkta52sdEOHuzxGywF93vo6SRimfu29qLFCLAPKIi31LFFiR7E71SvQ== X-Received: by 2002:a05:600c:5253:b0:40d:7fbe:e966 with SMTP id fc19-20020a05600c525300b0040d7fbee966mr110460wmb.40.1706664151673; Tue, 30 Jan 2024 17:22:31 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id f9-20020a056000036900b00339307d9d31sm11944425wrf.112.2024.01.30.17.22.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:30 -0800 (PST) Message-ID: In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:19 +0000 Subject: [PATCH v3 05/10] trailer: make trailer_info struct private Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Fcc: Sent To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver In 13211ae23f (trailer: separate public from internal portion of trailer_iterator, 2023-09-09) we moved trailer_info behind an anonymous struct to discourage use by trailer.h API users. However it still left open the possibility of external use of trailer_info itself. Now that there are no external users of trailer_info, we can make this struct private. Make this struct private by putting its definition inside trailer.c. This has two benefits: (1) it makes the surface area of the public facing interface (trailer.h) smaller, and (2) external API users are unable to peer inside this struct (because it is only ever exposed as an opaque pointer). This change exposes some deficiencies in the API, mainly with regard to information about the location of the trailer block that was parsed. Expose new API functions to access this information (needed by builtin/interpret-trailers.c). The idea in this patch to hide implementation details behind an "opaque pointer" is also known as the "pimpl" (pointer to implementation) idiom in C++ and is a common pattern in that language (where, for example, abstract classes only have pointers to concrete classes). However, the original inspiration to use this idiom does not come from C++, but instead the book "C Interfaces and Implementations: Techniques for Creating Reusable Software" [1]. This book recommends opaque pointers as a good design principle for designing C libraries, using the term "interface" as the functions defined in *.h (header) files and "implementation" as the corresponding *.c file which define the interfaces. The book says this about opaque pointers: ... clients can manipulate such pointers freely, but they can’t dereference them; that is, they can’t look at the innards of the structure pointed to by them. Only the implementation has that privilege. Opaque pointers hide representation details and help catch errors. In our case, "struct trailer_info" is now hidden from clients, and the ways in which this opaque pointer can be used is limited to the richness of the trailer.h file. In other words, trailer.h exclusively controls exactly how "trailer_info" pointers are to be used. [1] Hanson, David R. "C Interfaces and Implementations: Techniques for Creating Reusable Software". Addison Wesley, 1997. p. 22 Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 13 +-- trailer.c | 154 +++++++++++++++++++++++------------ trailer.h | 37 ++------- 3 files changed, 117 insertions(+), 87 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 5352ee65bd1..9e6ed6b65e2 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -141,7 +141,7 @@ static void interpret_trailers(const struct process_trailer_options *opts, LIST_HEAD(head); struct strbuf sb = STRBUF_INIT; struct strbuf trailer_block = STRBUF_INIT; - struct trailer_info info; + struct trailer_info *info; FILE *outfile = stdout; trailer_config_init(); @@ -151,13 +151,13 @@ static void interpret_trailers(const struct process_trailer_options *opts, if (opts->in_place) outfile = create_in_place_tempfile(file); - parse_trailers(opts, &info, sb.buf, &head); + info = parse_trailers(opts, sb.buf, &head); /* Print the lines before the trailers */ if (!opts->only_trailers) - fwrite(sb.buf, 1, info.trailer_block_start, outfile); + fwrite(sb.buf, 1, trailer_block_start(info), outfile); - if (!opts->only_trailers && !info.blank_line_before_trailer) + if (!opts->only_trailers && !blank_line_before_trailer_block(info)) fprintf(outfile, "\n"); @@ -176,11 +176,12 @@ static void interpret_trailers(const struct process_trailer_options *opts, strbuf_release(&trailer_block); free_trailers(&head); - trailer_info_release(&info); /* Print the lines after the trailers as is */ if (!opts->only_trailers) - fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile); + fwrite(sb.buf + trailer_block_end(info), 1, sb.len - trailer_block_end(info), outfile); + + trailer_info_release(info); if (opts->in_place) if (rename_tempfile(&trailers_tempfile, file)) diff --git a/trailer.c b/trailer.c index 5bcc9b0006c..63774cd068d 100644 --- a/trailer.c +++ b/trailer.c @@ -11,6 +11,27 @@ * Copyright (c) 2013, 2014 Christian Couder */ +struct trailer_info { + /* + * True if there is a blank line before the location pointed to by + * trailer_block_start. + */ + int blank_line_before_trailer; + + /* + * Offsets to the trailer block start and end positions in the input + * string. If no trailer block is found, these are both set to the + * "true" end of the input (find_end_of_log_message()). + */ + size_t trailer_block_start, trailer_block_end; + + /* + * Array of trailers found. + */ + char **trailers; + size_t trailer_nr; +}; + struct conf_info { char *name; char *key; @@ -1025,20 +1046,72 @@ void format_trailers(const struct process_trailer_options *opts, } } +static struct trailer_info *trailer_info_new(void) +{ + struct trailer_info *info = xcalloc(1, sizeof(*info)); + return info; +} + +static struct trailer_info *trailer_info_get(const struct process_trailer_options *opts, + const char *str) +{ + struct trailer_info *info = trailer_info_new(); + size_t end_of_log_message = 0, trailer_block_start = 0; + struct strbuf **trailer_lines, **ptr; + char **trailer_strings = NULL; + size_t nr = 0, alloc = 0; + char **last = NULL; + + trailer_config_init(); + + end_of_log_message = find_end_of_log_message(str, opts->no_divider); + trailer_block_start = find_trailer_block_start(str, end_of_log_message); + + trailer_lines = strbuf_split_buf(str + trailer_block_start, + end_of_log_message - trailer_block_start, + '\n', + 0); + for (ptr = trailer_lines; *ptr; ptr++) { + if (last && isspace((*ptr)->buf[0])) { + struct strbuf sb = STRBUF_INIT; + strbuf_attach(&sb, *last, strlen(*last), strlen(*last)); + strbuf_addbuf(&sb, *ptr); + *last = strbuf_detach(&sb, NULL); + continue; + } + ALLOC_GROW(trailer_strings, nr + 1, alloc); + trailer_strings[nr] = strbuf_detach(*ptr, NULL); + last = find_separator(trailer_strings[nr], separators) >= 1 + ? &trailer_strings[nr] + : NULL; + nr++; + } + strbuf_list_free(trailer_lines); + + info->blank_line_before_trailer = ends_with_blank_line(str, + trailer_block_start); + info->trailer_block_start = trailer_block_start; + info->trailer_block_end = end_of_log_message; + info->trailers = trailer_strings; + info->trailer_nr = nr; + + return info; +} + /* * Parse trailers in "str", populating the trailer info and "head" * linked list structure. */ -void parse_trailers(const struct process_trailer_options *opts, - struct trailer_info *info, - const char *str, - struct list_head *head) +struct trailer_info *parse_trailers(const struct process_trailer_options *opts, + const char *str, + struct list_head *head) { + struct trailer_info *info; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; size_t i; - trailer_info_get(info, str, opts); + info = trailer_info_get(opts, str); for (i = 0; i < info->trailer_nr; i++) { int separator_pos; @@ -1062,6 +1135,8 @@ void parse_trailers(const struct process_trailer_options *opts, strbuf_detach(&val, NULL)); } } + + return info; } void free_trailers(struct list_head *trailers) @@ -1073,47 +1148,19 @@ void free_trailers(struct list_head *trailers) } } -void trailer_info_get(struct trailer_info *info, const char *str, - const struct process_trailer_options *opts) +size_t trailer_block_start(struct trailer_info *info) { - size_t end_of_log_message = 0, trailer_block_start = 0; - struct strbuf **trailer_lines, **ptr; - char **trailer_strings = NULL; - size_t nr = 0, alloc = 0; - char **last = NULL; - - trailer_config_init(); - - end_of_log_message = find_end_of_log_message(str, opts->no_divider); - trailer_block_start = find_trailer_block_start(str, end_of_log_message); + return info->trailer_block_start; +} - trailer_lines = strbuf_split_buf(str + trailer_block_start, - end_of_log_message - trailer_block_start, - '\n', - 0); - for (ptr = trailer_lines; *ptr; ptr++) { - if (last && isspace((*ptr)->buf[0])) { - struct strbuf sb = STRBUF_INIT; - strbuf_attach(&sb, *last, strlen(*last), strlen(*last)); - strbuf_addbuf(&sb, *ptr); - *last = strbuf_detach(&sb, NULL); - continue; - } - ALLOC_GROW(trailer_strings, nr + 1, alloc); - trailer_strings[nr] = strbuf_detach(*ptr, NULL); - last = find_separator(trailer_strings[nr], separators) >= 1 - ? &trailer_strings[nr] - : NULL; - nr++; - } - strbuf_list_free(trailer_lines); +size_t trailer_block_end(struct trailer_info *info) +{ + return info->trailer_block_end; +} - info->blank_line_before_trailer = ends_with_blank_line(str, - trailer_block_start); - info->trailer_block_start = trailer_block_start; - info->trailer_block_end = end_of_log_message; - info->trailers = trailer_strings; - info->trailer_nr = nr; +int blank_line_before_trailer_block(struct trailer_info *info) +{ + return info->blank_line_before_trailer; } void trailer_info_release(struct trailer_info *info) @@ -1122,6 +1169,7 @@ void trailer_info_release(struct trailer_info *info) for (i = 0; i < info->trailer_nr; i++) free(info->trailers[i]); free(info->trailers); + free(info); } void format_trailers_from_commit(const struct process_trailer_options *opts, @@ -1129,30 +1177,30 @@ void format_trailers_from_commit(const struct process_trailer_options *opts, struct strbuf *out) { LIST_HEAD(head); - struct trailer_info info; - - parse_trailers(opts, &info, msg, &head); + struct trailer_info *info = parse_trailers(opts, msg, &head); /* If we want the whole block untouched, we can take the fast path. */ if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator && !opts->key_only && !opts->value_only && !opts->key_value_separator) { - strbuf_add(out, msg + info.trailer_block_start, - info.trailer_block_end - info.trailer_block_start); + strbuf_add(out, msg + info->trailer_block_start, + info->trailer_block_end - info->trailer_block_start); } else format_trailers(opts, &head, out); free_trailers(&head); - trailer_info_release(&info); + trailer_info_release(info); } void trailer_iterator_init(struct trailer_iterator *iter, const char *msg) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; + struct trailer_info *internal = trailer_info_new(); strbuf_init(&iter->key, 0); strbuf_init(&iter->val, 0); opts.no_divider = 1; - trailer_info_get(&iter->internal.info, msg, &opts); + iter->internal.info = internal; + iter->internal.info = trailer_info_get(&opts, msg); iter->internal.cur = 0; } @@ -1160,8 +1208,8 @@ int trailer_iterator_advance(struct trailer_iterator *iter) { char *line; int separator_pos; - if (iter->internal.cur < iter->internal.info.trailer_nr) { - line = iter->internal.info.trailers[iter->internal.cur++]; + if (iter->internal.cur < iter->internal.info->trailer_nr) { + line = iter->internal.info->trailers[iter->internal.cur++]; separator_pos = find_separator(line, separators); iter->is_trailer = (separator_pos > 0); @@ -1178,7 +1226,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter) void trailer_iterator_release(struct trailer_iterator *iter) { - trailer_info_release(&iter->internal.info); + trailer_info_release(iter->internal.info); strbuf_release(&iter->val); strbuf_release(&iter->key); } diff --git a/trailer.h b/trailer.h index a7599067acc..e19ddf84e64 100644 --- a/trailer.h +++ b/trailer.h @@ -4,6 +4,8 @@ #include "list.h" #include "strbuf.h" +struct trailer_info; + enum trailer_where { WHERE_DEFAULT, WHERE_END, @@ -29,27 +31,6 @@ int trailer_set_where(enum trailer_where *item, const char *value); int trailer_set_if_exists(enum trailer_if_exists *item, const char *value); int trailer_set_if_missing(enum trailer_if_missing *item, const char *value); -struct trailer_info { - /* - * True if there is a blank line before the location pointed to by - * trailer_block_start. - */ - int blank_line_before_trailer; - - /* - * Offsets to the trailer block start and end positions in the input - * string. If no trailer block is found, these are both set to the - * "true" end of the input (find_end_of_log_message()). - */ - size_t trailer_block_start, trailer_block_end; - - /* - * Array of trailers found. - */ - char **trailers; - size_t trailer_nr; -}; - /* * A list that represents newly-added trailers, such as those provided * with the --trailer command line option of git-interpret-trailers. @@ -89,13 +70,13 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head, void process_trailers_lists(struct list_head *head, struct list_head *arg_head); -void parse_trailers(const struct process_trailer_options *opts, - struct trailer_info *info, - const char *str, - struct list_head *head); +struct trailer_info *parse_trailers(const struct process_trailer_options *opts, + const char *str, + struct list_head *head); -void trailer_info_get(struct trailer_info *info, const char *str, - const struct process_trailer_options *opts); +size_t trailer_block_start(struct trailer_info *info); +size_t trailer_block_end(struct trailer_info *info); +int blank_line_before_trailer_block(struct trailer_info *info); void trailer_info_release(struct trailer_info *info); @@ -142,7 +123,7 @@ struct trailer_iterator { /* private */ struct { - struct trailer_info info; + struct trailer_info *info; size_t cur; } internal; }; From patchwork Wed Jan 31 01:22:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538476 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B09F863A7 for ; Wed, 31 Jan 2024 01:22:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664156; cv=none; b=hhJ6wBKW7VKCD3cHOyQZV8Fbmcm9CglWSMtGdfWwrJNMN63k+vL8cQB6UOJe3llw8+88k3dvHV1qa3MTVu93ICrsCAtK2ACcKLKhDANBpcDj9tVHJwmCwvnedjtxNaXnpa1ZFreOD03xACzosDzDP2QJv+nEOlf71nQIxcNMNMA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664156; c=relaxed/simple; bh=iw1yqPdnLg9qX5+cNnOQStRxa5xjUrhPu5eBt2kpSFA=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=SoVQi42a2T0z9b6H+u7aXfNyinXofAr/igtwkwjx+AxNUt/xTVGTrSgD8jN/8cgGaAyezdjb1MGR+3h5wS27HW2jwhUKKB/9n5VB8Bc9FqPBzlqKCwHb/abNpQKBS9ra9+HT0QKyaFS/8br6tgE5o1LhPRjuzsW0bn2tWjujvFE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kPhGg/ls; arc=none smtp.client-ip=209.85.221.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kPhGg/ls" Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-33ae6dfa923so2060151f8f.1 for ; Tue, 30 Jan 2024 17:22:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664152; x=1707268952; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=J2apEInBK31bE3Ei7TrhNRecpv+hVokhZkV20ydfezk=; b=kPhGg/lsXcESqG1sIgBXre1f9pWSmVfvNvf6Pzw1KqH6yJhQQLKjeQKEeqdTlKva95 lu6x3VtG1kPrxh8zZx1ZxbymosJJY6f3Ig6EcumRM83+rUbnsHtIMJlgbA/t5Nf7CkqT PeoGVaC9cTof/IoRp64VpUVi9hcvuuQPsrXW7TIopMdHZUz9gqXzPjotJxBtmlAQE7Qk AiwLSzaBsjVjXd6NAHYfffA9BCBryL6SCgdA4hLZRKwZT9P9X7NQrOE5E/a4fm2qeRWs GWL09d53/VTu3ZmNTdoBxBL2d+xwlMBgMDCq68zaJyxZebXlp+in18Bjkyi1/rz0gUi5 ZvKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664152; x=1707268952; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=J2apEInBK31bE3Ei7TrhNRecpv+hVokhZkV20ydfezk=; b=lRfMt7sAKwAM/GVisrVS9YLqBII7/SdG5sJeDZzIwTUHQ762JYGONtqPL5MjHBpPQ1 6KNI5t5giFjtRjDoJeiEqw3QFEdyZLgJRXafn3tf8KgCZjn57RVZb1zOt6Xr7yI7UBuk 28+XJTDm950HuqvpRLvWNuQxtVl4Yp1QN4C6UqsybgKY7wtGakFKff5yUnn4bcgvW8sa vp0JuF8p+PS0yL9pQMpCxkABIhyDbbw3w0Rs+aiyqa7m9Y4vL5PJn3Bknb7EmfjAtKZW AOlIm3tDMPZqwhsfAMRhZVlxgd3tRj4fzQAfUfnoIw6NkiRc/jN+002XAF2rG9jUaz+U 9Rfg== X-Gm-Message-State: AOJu0YxAooQYk0EOKzyB8qfR8YKqlZARLATBRB00umGPL3cXxm41Duw+ rboqJa4H9qjs9bi2XPLXnM/1TpxY88XyKHhoYWutP8EtBNLg6fhOoYJobnYV X-Google-Smtp-Source: AGHT+IEln37EtIx4xTJ91yI0jkJ3Pl9/7TVL3KG++KJcUjS5o5ZU4HC+v1ouh8bot13K2xgKp6nW/w== X-Received: by 2002:a5d:6b89:0:b0:33a:eda1:e68b with SMTP id n9-20020a5d6b89000000b0033aeda1e68bmr98940wrx.24.1706664152597; Tue, 30 Jan 2024 17:22:32 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id cx18-20020a056000093200b0033935779a23sm11991703wrb.89.2024.01.30.17.22.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:32 -0800 (PST) Message-ID: <0a9a7438c3ff39f1434087bf3ed6a9865758c803.1706664145.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:20 +0000 Subject: [PATCH v3 06/10] trailer: spread usage of "trailer_block" language Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver Deprecate the "trailer_info" struct name and replace it with "trailer_block". The main reason is to help readability, because "trailer_info" on the surface sounds like it's about a single trailer when in reality it is a collection of contiguous lines, at least 25% of which are trailers. Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 26 +++++----- trailer.c | 99 ++++++++++++++++++------------------ trailer.h | 18 +++---- 3 files changed, 71 insertions(+), 72 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 9e6ed6b65e2..9e41fa20b5f 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -140,8 +140,8 @@ static void interpret_trailers(const struct process_trailer_options *opts, { LIST_HEAD(head); struct strbuf sb = STRBUF_INIT; - struct strbuf trailer_block = STRBUF_INIT; - struct trailer_info *info; + struct strbuf tb = STRBUF_INIT; + struct trailer_block *trailer_block; FILE *outfile = stdout; trailer_config_init(); @@ -151,13 +151,13 @@ static void interpret_trailers(const struct process_trailer_options *opts, if (opts->in_place) outfile = create_in_place_tempfile(file); - info = parse_trailers(opts, sb.buf, &head); + trailer_block = parse_trailers(opts, sb.buf, &head); - /* Print the lines before the trailers */ + /* Print the lines before the trailer block */ if (!opts->only_trailers) - fwrite(sb.buf, 1, trailer_block_start(info), outfile); + fwrite(sb.buf, 1, trailer_block_start(trailer_block), outfile); - if (!opts->only_trailers && !blank_line_before_trailer_block(info)) + if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block)) fprintf(outfile, "\n"); @@ -171,17 +171,17 @@ static void interpret_trailers(const struct process_trailer_options *opts, } /* Print trailer block. */ - format_trailers(opts, &head, &trailer_block); - fwrite(trailer_block.buf, 1, trailer_block.len, outfile); - strbuf_release(&trailer_block); + format_trailers(opts, &head, &tb); + fwrite(tb.buf, 1, tb.len, outfile); + strbuf_release(&tb); free_trailers(&head); - /* Print the lines after the trailers as is */ + /* Print the lines after the trailer block as is */ if (!opts->only_trailers) - fwrite(sb.buf + trailer_block_end(info), 1, sb.len - trailer_block_end(info), outfile); - - trailer_info_release(info); + fwrite(sb.buf + trailer_block_end(trailer_block), + 1, sb.len - trailer_block_end(trailer_block), outfile); + trailer_block_release(trailer_block); if (opts->in_place) if (rename_tempfile(&trailers_tempfile, file)) diff --git a/trailer.c b/trailer.c index 63774cd068d..e2a48bea0ae 100644 --- a/trailer.c +++ b/trailer.c @@ -11,19 +11,20 @@ * Copyright (c) 2013, 2014 Christian Couder */ -struct trailer_info { +struct trailer_block { /* * True if there is a blank line before the location pointed to by - * trailer_block_start. + * "start". */ int blank_line_before_trailer; /* - * Offsets to the trailer block start and end positions in the input - * string. If no trailer block is found, these are both set to the - * "true" end of the input (find_end_of_log_message()). + * The locations of the start and end positions of the trailer block + * found, as offsets from the beginning of the source text from which + * this trailer block was parsed. If no trailer block is found, these + * are both set to 0. */ - size_t trailer_block_start, trailer_block_end; + size_t start, end; /* * Array of trailers found. @@ -1046,16 +1047,16 @@ void format_trailers(const struct process_trailer_options *opts, } } -static struct trailer_info *trailer_info_new(void) +static struct trailer_block *trailer_block_new(void) { - struct trailer_info *info = xcalloc(1, sizeof(*info)); - return info; + struct trailer_block *trailer_block = xcalloc(1, sizeof(*trailer_block)); + return trailer_block; } -static struct trailer_info *trailer_info_get(const struct process_trailer_options *opts, - const char *str) +static struct trailer_block *trailer_block_get(const struct process_trailer_options *opts, + const char *str) { - struct trailer_info *info = trailer_info_new(); + struct trailer_block *trailer_block = trailer_block_new(); size_t end_of_log_message = 0, trailer_block_start = 0; struct strbuf **trailer_lines, **ptr; char **trailer_strings = NULL; @@ -1088,34 +1089,34 @@ static struct trailer_info *trailer_info_get(const struct process_trailer_option } strbuf_list_free(trailer_lines); - info->blank_line_before_trailer = ends_with_blank_line(str, - trailer_block_start); - info->trailer_block_start = trailer_block_start; - info->trailer_block_end = end_of_log_message; - info->trailers = trailer_strings; - info->trailer_nr = nr; + trailer_block->blank_line_before_trailer = ends_with_blank_line(str, + trailer_block_start); + trailer_block->start = trailer_block_start; + trailer_block->end = end_of_log_message; + trailer_block->trailers = trailer_strings; + trailer_block->trailer_nr = nr; - return info; + return trailer_block; } /* - * Parse trailers in "str", populating the trailer info and "head" - * linked list structure. + * Parse trailers in "str", populating the trailer_block info and "head" linked + * list structure. */ -struct trailer_info *parse_trailers(const struct process_trailer_options *opts, - const char *str, - struct list_head *head) +struct trailer_block *parse_trailers(const struct process_trailer_options *opts, + const char *str, + struct list_head *head) { - struct trailer_info *info; + struct trailer_block *trailer_block; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; size_t i; - info = trailer_info_get(opts, str); + trailer_block = trailer_block_get(opts, str); - for (i = 0; i < info->trailer_nr; i++) { + for (i = 0; i < trailer_block->trailer_nr; i++) { int separator_pos; - char *trailer = info->trailers[i]; + char *trailer = trailer_block->trailers[i]; if (trailer[0] == comment_line_char) continue; separator_pos = find_separator(trailer, separators); @@ -1136,7 +1137,7 @@ struct trailer_info *parse_trailers(const struct process_trailer_options *opts, } } - return info; + return trailer_block; } void free_trailers(struct list_head *trailers) @@ -1148,28 +1149,28 @@ void free_trailers(struct list_head *trailers) } } -size_t trailer_block_start(struct trailer_info *info) +size_t trailer_block_start(struct trailer_block *trailer_block) { - return info->trailer_block_start; + return trailer_block->start; } -size_t trailer_block_end(struct trailer_info *info) +size_t trailer_block_end(struct trailer_block *trailer_block) { - return info->trailer_block_end; + return trailer_block->end; } -int blank_line_before_trailer_block(struct trailer_info *info) +int blank_line_before_trailer_block(struct trailer_block *trailer_block) { - return info->blank_line_before_trailer; + return trailer_block->blank_line_before_trailer; } -void trailer_info_release(struct trailer_info *info) +void trailer_block_release(struct trailer_block *trailer_block) { size_t i; - for (i = 0; i < info->trailer_nr; i++) - free(info->trailers[i]); - free(info->trailers); - free(info); + for (i = 0; i < trailer_block->trailer_nr; i++) + free(trailer_block->trailers[i]); + free(trailer_block->trailers); + free(trailer_block); } void format_trailers_from_commit(const struct process_trailer_options *opts, @@ -1177,30 +1178,28 @@ void format_trailers_from_commit(const struct process_trailer_options *opts, struct strbuf *out) { LIST_HEAD(head); - struct trailer_info *info = parse_trailers(opts, msg, &head); + struct trailer_block *trailer_block = parse_trailers(opts, msg, &head); /* If we want the whole block untouched, we can take the fast path. */ if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator && !opts->key_only && !opts->value_only && !opts->key_value_separator) { - strbuf_add(out, msg + info->trailer_block_start, - info->trailer_block_end - info->trailer_block_start); + strbuf_add(out, msg + trailer_block->start, + trailer_block->end - trailer_block->start); } else format_trailers(opts, &head, out); free_trailers(&head); - trailer_info_release(info); + trailer_block_release(trailer_block); } void trailer_iterator_init(struct trailer_iterator *iter, const char *msg) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; - struct trailer_info *internal = trailer_info_new(); strbuf_init(&iter->key, 0); strbuf_init(&iter->val, 0); opts.no_divider = 1; - iter->internal.info = internal; - iter->internal.info = trailer_info_get(&opts, msg); + iter->internal.trailer_block = trailer_block_get(&opts, msg); iter->internal.cur = 0; } @@ -1208,8 +1207,8 @@ int trailer_iterator_advance(struct trailer_iterator *iter) { char *line; int separator_pos; - if (iter->internal.cur < iter->internal.info->trailer_nr) { - line = iter->internal.info->trailers[iter->internal.cur++]; + if (iter->internal.cur < iter->internal.trailer_block->trailer_nr) { + line = iter->internal.trailer_block->trailers[iter->internal.cur++]; separator_pos = find_separator(line, separators); iter->is_trailer = (separator_pos > 0); @@ -1226,7 +1225,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter) void trailer_iterator_release(struct trailer_iterator *iter) { - trailer_info_release(iter->internal.info); + trailer_block_release(iter->internal.trailer_block); strbuf_release(&iter->val); strbuf_release(&iter->key); } diff --git a/trailer.h b/trailer.h index e19ddf84e64..e74f9189c0a 100644 --- a/trailer.h +++ b/trailer.h @@ -4,7 +4,7 @@ #include "list.h" #include "strbuf.h" -struct trailer_info; +struct trailer_block; enum trailer_where { WHERE_DEFAULT, @@ -70,15 +70,15 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head, void process_trailers_lists(struct list_head *head, struct list_head *arg_head); -struct trailer_info *parse_trailers(const struct process_trailer_options *opts, - const char *str, - struct list_head *head); +struct trailer_block *parse_trailers(const struct process_trailer_options *opts, + const char *str, + struct list_head *head); -size_t trailer_block_start(struct trailer_info *info); -size_t trailer_block_end(struct trailer_info *info); -int blank_line_before_trailer_block(struct trailer_info *info); +size_t trailer_block_start(struct trailer_block *trailer_block); +size_t trailer_block_end(struct trailer_block *trailer_block); +int blank_line_before_trailer_block(struct trailer_block *trailer_block); -void trailer_info_release(struct trailer_info *info); +void trailer_block_release(struct trailer_block *trailer_block); void trailer_config_init(void); void format_trailers(const struct process_trailer_options *opts, @@ -123,7 +123,7 @@ struct trailer_iterator { /* private */ struct { - struct trailer_info *info; + struct trailer_block *trailer_block; size_t cur; } internal; }; From patchwork Wed Jan 31 01:22:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538478 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B5617470 for ; Wed, 31 Jan 2024 01:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664158; cv=none; b=hitlnptZ0G5jgEdeiZ+If//YB/+bpevow7fyB2FPA+5ULNmH75LyVB+jOPX0dQQ/BN7mzCOffIPKL87m5AcP8KtrerDkIGux7dkvCO8Mu6xG2o9SzJULrVih1Ijsuani/XONOu5rfD2qeqNx+Xsk+/j1Mbg6mFznRjVbB609cbU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664158; c=relaxed/simple; bh=KXtLdDt/5aSPe9I4lvB2zwZXZzMW3oNn2sEaTi0ECTw=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=qakjvbuSQeuwfzwH52VOR3H21AksiFKrgwRxszyo6dc6eiRooKhPkDLgBSw/mTJsOPVDzFAligW52qOreEtP5OytimzVJE48GXTPbFZUGzg91HC+1jULkc39VJenKxVoSzobPymZ71BxJK8Z4gACeuQteI7srTfO//H7SLk8fKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hQpmvU3z; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hQpmvU3z" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-33ae4eb360aso2728361f8f.0 for ; Tue, 30 Jan 2024 17:22:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664154; x=1707268954; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=r0Z4RGuY8GEC/Uphd6PtK6kCa/oocHOfbIbtSAJ0z2w=; b=hQpmvU3zzGYek7YZBXailf9aZThxADxB4+At/PzVNLoahwSorfPzfs4z3VJc+32+Ta u6vYfxmJ7TCh5d6z7hRMLsZTEMuYA1kA/Q0WYaYGkXAnXfr+RaFtrBU5x5z9gBQlty0t OuB8fnVFHcPiR7ATp4QaOF0LRws3K/DQ/xlHYBpwvax1r5p5Dmb7LOaRHUJW8A8bZDqy PSYDY1zDruHd7O/x32EikKcFSc2VZ4+dztrUTLtt5pbpjfSCMXBJrUU1cL3U4Ud+NGpi Ys7qHJAKHKmb0xsOiov9dwzKGjC7KJ33h/FnSJFoiZeBo62PRM4PodLfL0G5BnRpNt/h F6AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664154; x=1707268954; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=r0Z4RGuY8GEC/Uphd6PtK6kCa/oocHOfbIbtSAJ0z2w=; b=wB6VMfHWN9hon3rAD67OWewFtjN2FRxJjyoO8nPdovQwnBsv6TaA4iDhwRyAoYzoWC 8az/8nsCrniDjhMNPRrn57e0ctvLyHf8mpCuUJhPfaZMnRMfblIfGy64BdoYQleI0/tO HvfJGqRCbYIKATe9dGdjtPqyJOLFgFIv2icnAt6pMB2O5pcftpFXrZzRX02T9NfmMB2P 2/A5Jcy3ako/Qs8+6fXrPRRhPcFfXZvEXpVC4cLMxkxgaNu8sKVOuq5CRcVW3J/X02Rv fm2UMoUSU7HM6W7R1lxvGFpCnVrCn/rxcPyLkqeSeJv2KOtRV68f/jbr+lQ2aRvKxwlN 1OIw== X-Gm-Message-State: AOJu0YxN7TUxjjQTWhskGxZYvNPpUGg9qsN+oI7oQEJBeu+Ph/t53Imt acKUlEnfHG+EekKI17qNYt1b0vRQYjOHAcOC+YRg3bttpP6QSPvxT2ZIpfBO X-Google-Smtp-Source: AGHT+IHbDYf2fj2xNg6gU3mo8xxh4d767hpOHI8Aw6ro+hWdSep+po2ZDbAUvf5eB5GLpZe8WKCzkg== X-Received: by 2002:adf:fbc9:0:b0:33b:149:24b4 with SMTP id d9-20020adffbc9000000b0033b014924b4mr116939wrs.17.1706664153380; Tue, 30 Jan 2024 17:22:33 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n16-20020adfe790000000b0033afed6e9desm1270090wrm.98.2024.01.30.17.22.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:32 -0800 (PST) Message-ID: <97e5d86ddf0ea25df1b512dfbf620910298c1b02.1706664145.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:21 +0000 Subject: [PATCH v3 07/10] trailer: prepare to move parse_trailers_from_command_line_args() to builtin Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver Expose more functions in the trailer.h API, in preparation for moving out parse_trailers_from_command_line_args() to interpret-trailer.c, because the trailer API should not be concerned with command line arguments (as they have nothing to do with trailers themselves). The interpret-trailers builtin is the only caller of this function. Rename add_arg_item() to trailer_add_arg_item() because it will have to be exposed as an API function in the next patch. Rename new_trailers_clear() to free_new_trailers() because it will be promoted into an API function; the API already has free_trailers(), so using the "free_*" naming style will keep it consistent. Also rename "conf_info" to "trailer_conf" for readability, dropping the low-value "_info" suffix as we did earlier in this series for "trailer_info" to "trailer_block". Helped-by: Josh Steadmon Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 6 +-- trailer.c | 86 ++++++++++++++++++------------------ trailer.h | 10 +++++ 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 9e41fa20b5f..9f0ba39b317 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -45,7 +45,7 @@ static int option_parse_if_missing(const struct option *opt, return trailer_set_if_missing(opt->value, arg); } -static void new_trailers_clear(struct list_head *trailers) +static void free_new_trailers(struct list_head *trailers) { struct list_head *pos, *tmp; struct new_trailer_item *item; @@ -64,7 +64,7 @@ static int option_parse_trailer(const struct option *opt, struct new_trailer_item *item; if (unset) { - new_trailers_clear(trailers); + free_new_trailers(trailers); return 0; } @@ -238,7 +238,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) interpret_trailers(&opts, &trailers, NULL); } - new_trailers_clear(&trailers); + free_new_trailers(&trailers); return 0; } diff --git a/trailer.c b/trailer.c index e2a48bea0ae..c16f552b463 100644 --- a/trailer.c +++ b/trailer.c @@ -33,7 +33,7 @@ struct trailer_block { size_t trailer_nr; }; -struct conf_info { +struct trailer_conf { char *name; char *key; char *command; @@ -43,7 +43,7 @@ struct conf_info { enum trailer_if_missing if_missing; }; -static struct conf_info default_conf_info; +static struct trailer_conf default_trailer_conf; struct trailer_item { struct list_head list; @@ -59,7 +59,7 @@ struct arg_item { struct list_head list; char *token; char *value; - struct conf_info conf; + struct trailer_conf conf; }; static LIST_HEAD(conf_head); @@ -210,7 +210,7 @@ static int check_if_different(struct trailer_item *in_tok, return 1; } -static char *apply_command(struct conf_info *conf, const char *arg) +static char *apply_command(struct trailer_conf *conf, const char *arg) { struct strbuf cmd = STRBUF_INIT; struct strbuf buf = STRBUF_INIT; @@ -424,7 +424,8 @@ int trailer_set_if_missing(enum trailer_if_missing *item, const char *value) return 0; } -static void duplicate_conf(struct conf_info *dst, const struct conf_info *src) +void duplicate_trailer_conf(struct trailer_conf *dst, + const struct trailer_conf *src) { *dst = *src; dst->name = xstrdup_or_null(src->name); @@ -447,7 +448,7 @@ static struct arg_item *get_conf_item(const char *name) /* Item does not already exists, create it */ CALLOC_ARRAY(item, 1); - duplicate_conf(&item->conf, &default_conf_info); + duplicate_trailer_conf(&item->conf, &default_trailer_conf); item->conf.name = xstrdup(name); list_add_tail(&item->list, &conf_head); @@ -482,17 +483,17 @@ static int git_trailer_default_config(const char *conf_key, const char *value, variable_name = strrchr(trailer_item, '.'); if (!variable_name) { if (!strcmp(trailer_item, "where")) { - if (trailer_set_where(&default_conf_info.where, + if (trailer_set_where(&default_trailer_conf.where, value) < 0) warning(_("unknown value '%s' for key '%s'"), value, conf_key); } else if (!strcmp(trailer_item, "ifexists")) { - if (trailer_set_if_exists(&default_conf_info.if_exists, + if (trailer_set_if_exists(&default_trailer_conf.if_exists, value) < 0) warning(_("unknown value '%s' for key '%s'"), value, conf_key); } else if (!strcmp(trailer_item, "ifmissing")) { - if (trailer_set_if_missing(&default_conf_info.if_missing, + if (trailer_set_if_missing(&default_trailer_conf.if_missing, value) < 0) warning(_("unknown value '%s' for key '%s'"), value, conf_key); @@ -511,7 +512,7 @@ static int git_trailer_config(const char *conf_key, const char *value, { const char *trailer_item, *variable_name; struct arg_item *item; - struct conf_info *conf; + struct trailer_conf *conf; char *name = NULL; enum trailer_info_type type; int i; @@ -585,9 +586,9 @@ void trailer_config_init(void) return; /* Default config must be setup first */ - default_conf_info.where = WHERE_END; - default_conf_info.if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR; - default_conf_info.if_missing = MISSING_ADD; + default_trailer_conf.where = WHERE_END; + default_trailer_conf.if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR; + default_trailer_conf.if_missing = MISSING_ADD; git_config(git_trailer_default_config, NULL); git_config(git_trailer_config, NULL); configured = 1; @@ -620,7 +621,7 @@ static int token_matches_item(const char *tok, struct arg_item *item, size_t tok * distinguished from the non-well-formed-line case (in which this function * returns -1) because some callers of this function need such a distinction. */ -static ssize_t find_separator(const char *line, const char *separators) +ssize_t find_separator(const char *line, const char *separators) { int whitespace_found = 0; const char *c; @@ -645,28 +646,28 @@ static ssize_t find_separator(const char *line, const char *separators) * * If separator_pos is -1, interpret the whole trailer as a token. */ -static void parse_trailer(struct strbuf *tok, struct strbuf *val, - const struct conf_info **conf, const char *trailer, - ssize_t separator_pos) +void parse_trailer(const char *line, ssize_t separator_pos, + struct strbuf *tok, struct strbuf *val, + const struct trailer_conf **conf) { struct arg_item *item; size_t tok_len; struct list_head *pos; if (separator_pos != -1) { - strbuf_add(tok, trailer, separator_pos); + strbuf_add(tok, line, separator_pos); strbuf_trim(tok); - strbuf_addstr(val, trailer + separator_pos + 1); + strbuf_addstr(val, line + separator_pos + 1); strbuf_trim(val); } else { - strbuf_addstr(tok, trailer); + strbuf_addstr(tok, line); strbuf_trim(tok); } /* Lookup if the token matches something in the config */ tok_len = token_len_without_separator(tok->buf, tok->len); if (conf) - *conf = &default_conf_info; + *conf = &default_trailer_conf; list_for_each(pos, &conf_head) { item = list_entry(pos, struct arg_item, list); if (token_matches_item(tok->buf, item, tok_len)) { @@ -690,14 +691,14 @@ static struct trailer_item *add_trailer_item(struct list_head *head, char *tok, return new_item; } -static void add_arg_item(struct list_head *arg_head, char *tok, char *val, - const struct conf_info *conf, - const struct new_trailer_item *new_trailer_item) +static void trailer_add_arg_item(struct list_head *arg_head, char *tok, char *val, + const struct trailer_conf *conf, + const struct new_trailer_item *new_trailer_item) { struct arg_item *new_item = xcalloc(1, sizeof(*new_item)); new_item->token = tok; new_item->value = val; - duplicate_conf(&new_item->conf, conf); + duplicate_trailer_conf(&new_item->conf, conf); if (new_trailer_item) { if (new_trailer_item->where != WHERE_DEFAULT) new_item->conf.where = new_trailer_item->where; @@ -718,10 +719,10 @@ void parse_trailers_from_config(struct list_head *config_head) list_for_each(pos, &conf_head) { item = list_entry(pos, struct arg_item, list); if (item->conf.command) - add_arg_item(config_head, - xstrdup(token_from_item(item, NULL)), - xstrdup(""), - &item->conf, NULL); + trailer_add_arg_item(config_head, + xstrdup(token_from_item(item, NULL)), + xstrdup(""), + &item->conf, NULL); } } @@ -730,7 +731,7 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head, { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; - const struct conf_info *conf; + const struct trailer_conf *conf; struct list_head *pos; /* @@ -753,12 +754,11 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head, (int) sb.len, sb.buf); strbuf_release(&sb); } else { - parse_trailer(&tok, &val, &conf, tr->text, - separator_pos); - add_arg_item(arg_head, - strbuf_detach(&tok, NULL), - strbuf_detach(&val, NULL), - conf, tr); + parse_trailer(tr->text, separator_pos, &tok, &val, &conf); + trailer_add_arg_item(arg_head, + strbuf_detach(&tok, NULL), + strbuf_detach(&val, NULL), + conf, tr); } } @@ -1116,20 +1116,19 @@ struct trailer_block *parse_trailers(const struct process_trailer_options *opts, for (i = 0; i < trailer_block->trailer_nr; i++) { int separator_pos; - char *trailer = trailer_block->trailers[i]; - if (trailer[0] == comment_line_char) + char *line = trailer_block->trailers[i]; + if (line[0] == comment_line_char) continue; - separator_pos = find_separator(trailer, separators); + separator_pos = find_separator(line, separators); if (separator_pos >= 1) { - parse_trailer(&tok, &val, NULL, trailer, - separator_pos); + parse_trailer(line, separator_pos, &tok, &val, NULL); if (opts->unfold) unfold_value(&val); add_trailer_item(head, strbuf_detach(&tok, NULL), strbuf_detach(&val, NULL)); } else if (!opts->only_trailers) { - strbuf_addstr(&val, trailer); + strbuf_addstr(&val, line); strbuf_strip_suffix(&val, "\n"); add_trailer_item(head, NULL, @@ -1215,8 +1214,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter) iter->raw = line; strbuf_reset(&iter->key); strbuf_reset(&iter->val); - parse_trailer(&iter->key, &iter->val, NULL, - line, separator_pos); + parse_trailer(line, separator_pos, &iter->key, &iter->val, NULL); unfold_value(&iter->val); return 1; } diff --git a/trailer.h b/trailer.h index e74f9189c0a..d724263e4f6 100644 --- a/trailer.h +++ b/trailer.h @@ -5,6 +5,7 @@ #include "strbuf.h" struct trailer_block; +struct trailer_conf; enum trailer_where { WHERE_DEFAULT, @@ -45,6 +46,9 @@ struct new_trailer_item { enum trailer_if_missing if_missing; }; +void duplicate_trailer_conf(struct trailer_conf *dst, + const struct trailer_conf *src); + struct process_trailer_options { int in_place; int trim_empty; @@ -70,6 +74,12 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head, void process_trailers_lists(struct list_head *head, struct list_head *arg_head); +ssize_t find_separator(const char *line, const char *separators); + +void parse_trailer(const char *line, ssize_t separator_pos, + struct strbuf *tok, struct strbuf *val, + const struct trailer_conf **conf); + struct trailer_block *parse_trailers(const struct process_trailer_options *opts, const char *str, struct list_head *head); From patchwork Wed Jan 31 01:22:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538477 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 418057492 for ; Wed, 31 Jan 2024 01:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664158; cv=none; b=uEPzLkTuN2K3YwFi3cRnL48q1baK1xhBEUV9nY/K1yOxRL8vwh5Ts2R3OZ009RICLP0WVrULNACSC0XKMGm/dfefuEkXpRd8jpKt6hmjrktlqcBp6BLmzowUAl4a58GMgrM2Ya4bg/nszpXDDGXlNza3ZUP4eqmRXALw0XaP0d4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664158; c=relaxed/simple; bh=WKXUpNCZQpjfyLiAh3bcKFnCovOwMOM6pPDSExzaaNY=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=BMiQ3JYdTuhaZ8t5yh48xtmsetxFnG/qlTGOHJUORAoo5XXQh+2Z3fSs80r/buXfhscwJGxJBWPJfzhVmNXJ5+9TAhptNerRPoQwVRQBx12E/TWjjxBE2270MoiW7JeQSfyhqApkswubmktQQTusr352BtIY4vvqBdUoKBWh/9E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VwtRK5gx; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VwtRK5gx" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-33ae3154cf8so2351455f8f.3 for ; Tue, 30 Jan 2024 17:22:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664154; x=1707268954; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=PQvmqV0OISwBdzCAoRM4EbupczYBhodAkHpQYhhvKyQ=; b=VwtRK5gx98Q96vlMb82h5q1u8UQhdblT7GarOj72wHZxY6+DLSOtP2HKBObRHugOZw 0Xpyo1Qq3SijgNX735s52Uwsq0eRUE8vIyXee/IRYW5xC1jxvkLaiIdEhCDHx5TK7W7h Lt66q5MsJiS21lnoNUB4Uks6dCKjZZhDYubDqLf/+jqYjPvLMCJFcce3B63xdWV/niIU SmJ6ExWfkkhNeOmwZwoi0wCLCyK7U4CLPDX9Fnzr9hbpmZZLXX3FYZjkp5z9TjEcwarg Ka/+fawbOiIAKqbuo2Zt9v2Zl+BnU5XWeDGHdJZri/KGnkqnYmho6jWsuIb16TF5mOYQ mB0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664154; x=1707268954; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PQvmqV0OISwBdzCAoRM4EbupczYBhodAkHpQYhhvKyQ=; b=ITBTJwprnfXc9dyByq+LGz3buieBMSqrKof0N0KCNH8SmY6zg7dgCeWxOeu7hBSa75 8pjWqIMgsgE4rvKOt3LxZECoqGg5tO1k7p1H6XU4x79Zw043sR7UvyzHQvZx15Kq86fQ /g3/a96ON6Ttyn3nxPaSDYu8UtOud9zfjEfH7PPfxjyPDS/THp0LwH07gmDPKQO69tJo 2owjJ/lm6/xCoU2LS4GzNzIvZS+NXCJUdA5ds8S3r3LX1pJPu3OwBM19E+Juy6cqZbTc wEdMVq9yhQdaHPczwpDKRurMtHiBPdeiISJueL2FAHmtP9H4nvYKiMHnmyPdczjzru3m LLdg== X-Gm-Message-State: AOJu0YyPqWOeHkvQEbPBb4dFzN+zTFGJgC14kS0v2e4Ic0V3z5f2koOa jRSLa9YHlMNP0Rc8EOxPmoj9fWDBl5LtRIT2/D8vdD3Fofbb8n5qyA+jqLir X-Google-Smtp-Source: AGHT+IEahtMrJGYNxP0CXorB6l7c5F7HsIes5E1OHH/2GOh7CDQvcWfZ3RnhPYmCK+GfvN/pjlH3DA== X-Received: by 2002:a5d:6781:0:b0:33a:d0da:5e4 with SMTP id v1-20020a5d6781000000b0033ad0da05e4mr97568wru.6.1706664153991; Tue, 30 Jan 2024 17:22:33 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id fa8-20020a056000258800b0033afb7c68a7sm2923341wrb.55.2024.01.30.17.22.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:33 -0800 (PST) Message-ID: <465dc51cdcba28d235241021bc52369f6082d329.1706664145.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:22 +0000 Subject: [PATCH v3 08/10] trailer: move arg handling to interpret-trailers.c Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver We don't move the "arg_item" struct to interpret-trailers.c, because it is now a struct that contains information about trailers that could be added into the input text's own trailers. This is a generic concept that extends beyond trailers defined as CLI arguments (it applies to trailers defined in configuration as well). We will rename "arg_item" to "trailer_template" in a follow-up patch to keep the diff here small. Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 88 ++++++++++++++++++++++-------------- trailer.c | 62 ++++++++++++++++++------- trailer.h | 12 +++++ 3 files changed, 112 insertions(+), 50 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 9f0ba39b317..9a902012912 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -45,23 +45,17 @@ static int option_parse_if_missing(const struct option *opt, return trailer_set_if_missing(opt->value, arg); } -static void free_new_trailers(struct list_head *trailers) -{ - struct list_head *pos, *tmp; - struct new_trailer_item *item; - - list_for_each_safe(pos, tmp, trailers) { - item = list_entry(pos, struct new_trailer_item, list); - list_del(pos); - free(item); - } -} +static char *cl_separators; static int option_parse_trailer(const struct option *opt, const char *arg, int unset) { struct list_head *trailers = opt->value; - struct new_trailer_item *item; + struct strbuf tok = STRBUF_INIT; + struct strbuf val = STRBUF_INIT; + const struct trailer_conf *conf; + struct trailer_conf *conf_current = new_trailer_conf(); + ssize_t separator_pos; if (unset) { free_new_trailers(trailers); @@ -71,12 +65,31 @@ static int option_parse_trailer(const struct option *opt, if (!arg) return -1; - item = xmalloc(sizeof(*item)); - item->text = arg; - item->where = where; - item->if_exists = if_exists; - item->if_missing = if_missing; - list_add_tail(&item->list, trailers); + separator_pos = find_separator(arg, cl_separators); + if (separator_pos) { + parse_trailer(arg, separator_pos, &tok, &val, &conf); + duplicate_trailer_conf(conf_current, conf); + + /* + * Override conf_current with settings specified via CLI flags. + */ + trailer_conf_set(where, if_exists, if_missing, conf_current); + + trailer_add_arg_item(strbuf_detach(&tok, NULL), + strbuf_detach(&val, NULL), + conf_current, + trailers); + } else { + struct strbuf sb = STRBUF_INIT; + strbuf_addstr(&sb, arg); + strbuf_trim(&sb); + error(_("empty trailer token in trailer '%.*s'"), + (int) sb.len, sb.buf); + strbuf_release(&sb); + } + + free(conf_current); + return 0; } @@ -135,7 +148,7 @@ static void read_input_file(struct strbuf *sb, const char *file) } static void interpret_trailers(const struct process_trailer_options *opts, - struct list_head *new_trailer_head, + struct list_head *arg_trailers, const char *file) { LIST_HEAD(head); @@ -144,8 +157,6 @@ static void interpret_trailers(const struct process_trailer_options *opts, struct trailer_block *trailer_block; FILE *outfile = stdout; - trailer_config_init(); - read_input_file(&sb, file); if (opts->in_place) @@ -162,12 +173,7 @@ static void interpret_trailers(const struct process_trailer_options *opts, if (!opts->only_input) { - LIST_HEAD(config_head); - LIST_HEAD(arg_head); - parse_trailers_from_config(&config_head); - parse_trailers_from_command_line_args(&arg_head, new_trailer_head); - list_splice(&config_head, &arg_head); - process_trailers_lists(&head, &arg_head); + process_trailers_lists(&head, arg_trailers); } /* Print trailer block. */ @@ -193,7 +199,8 @@ static void interpret_trailers(const struct process_trailer_options *opts, int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; - LIST_HEAD(trailers); + LIST_HEAD(configured_trailers); + LIST_HEAD(arg_trailers); struct option options[] = { OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")), @@ -212,33 +219,48 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) OPT_CALLBACK_F(0, "parse", &opts, NULL, N_("alias for --only-trailers --only-input --unfold"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse), OPT_BOOL(0, "no-divider", &opts.no_divider, N_("do not treat \"---\" as the end of input")), - OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"), + OPT_CALLBACK(0, "trailer", &arg_trailers, N_("trailer"), N_("trailer(s) to add"), option_parse_trailer), OPT_END() }; git_config(git_default_config, NULL); + trailer_config_init(); + + if (!opts.only_input) { + parse_trailers_from_config(&configured_trailers); + } + + /* + * In command-line arguments, '=' is accepted (in addition to the + * separators that are defined). + */ + cl_separators = xstrfmt("=%s", trailer_default_separators()); argc = parse_options(argc, argv, prefix, options, git_interpret_trailers_usage, 0); - if (opts.only_input && !list_empty(&trailers)) + free(cl_separators); + + if (opts.only_input && !list_empty(&arg_trailers)) usage_msg_opt( _("--trailer with --only-input does not make sense"), git_interpret_trailers_usage, options); + list_splice(&configured_trailers, &arg_trailers); + if (argc) { int i; for (i = 0; i < argc; i++) - interpret_trailers(&opts, &trailers, argv[i]); + interpret_trailers(&opts, &arg_trailers, argv[i]); } else { if (opts.in_place) die(_("no input file given for in-place editing")); - interpret_trailers(&opts, &trailers, NULL); + interpret_trailers(&opts, &arg_trailers, NULL); } - free_new_trailers(&trailers); + free_new_trailers(&arg_trailers); return 0; } diff --git a/trailer.c b/trailer.c index c16f552b463..19637ff295d 100644 --- a/trailer.c +++ b/trailer.c @@ -66,6 +66,11 @@ static LIST_HEAD(conf_head); static char *separators = ":"; +const char *trailer_default_separators(void) +{ + return separators; +} + static int configured; #define TRAILER_ARG_STRING "$ARG" @@ -424,6 +429,25 @@ int trailer_set_if_missing(enum trailer_if_missing *item, const char *value) return 0; } +void trailer_conf_set(enum trailer_where where, + enum trailer_if_exists if_exists, + enum trailer_if_missing if_missing, + struct trailer_conf *conf) +{ + if (where != WHERE_DEFAULT) + conf->where = where; + if (if_exists != EXISTS_DEFAULT) + conf->if_exists = if_exists; + if (if_missing != MISSING_DEFAULT) + conf->if_missing = if_missing; +} + +struct trailer_conf *new_trailer_conf(void) +{ + struct trailer_conf *new = xcalloc(1, sizeof(*new)); + return new; +} + void duplicate_trailer_conf(struct trailer_conf *dst, const struct trailer_conf *src) { @@ -642,6 +666,9 @@ ssize_t find_separator(const char *line, const char *separators) /* * Obtain the token, value, and conf from the given trailer. * + * The conf needs special handling. We first read hardcoded defaults, and + * override them if we find a matching trailer configuration. + * * separator_pos must not be 0, since the token cannot be an empty string. * * If separator_pos is -1, interpret the whole trailer as a token. @@ -691,22 +718,13 @@ static struct trailer_item *add_trailer_item(struct list_head *head, char *tok, return new_item; } -static void trailer_add_arg_item(struct list_head *arg_head, char *tok, char *val, - const struct trailer_conf *conf, - const struct new_trailer_item *new_trailer_item) +void trailer_add_arg_item(char *tok, char *val, const struct trailer_conf *conf, + struct list_head *arg_head) { struct arg_item *new_item = xcalloc(1, sizeof(*new_item)); new_item->token = tok; new_item->value = val; duplicate_trailer_conf(&new_item->conf, conf); - if (new_trailer_item) { - if (new_trailer_item->where != WHERE_DEFAULT) - new_item->conf.where = new_trailer_item->where; - if (new_trailer_item->if_exists != EXISTS_DEFAULT) - new_item->conf.if_exists = new_trailer_item->if_exists; - if (new_trailer_item->if_missing != MISSING_DEFAULT) - new_item->conf.if_missing = new_trailer_item->if_missing; - } list_add_tail(&new_item->list, arg_head); } @@ -719,10 +737,10 @@ void parse_trailers_from_config(struct list_head *config_head) list_for_each(pos, &conf_head) { item = list_entry(pos, struct arg_item, list); if (item->conf.command) - trailer_add_arg_item(config_head, - xstrdup(token_from_item(item, NULL)), + trailer_add_arg_item(xstrdup(token_from_item(item, NULL)), xstrdup(""), - &item->conf, NULL); + &item->conf, + config_head); } } @@ -755,10 +773,10 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head, strbuf_release(&sb); } else { parse_trailer(tr->text, separator_pos, &tok, &val, &conf); - trailer_add_arg_item(arg_head, - strbuf_detach(&tok, NULL), + trailer_add_arg_item(strbuf_detach(&tok, NULL), strbuf_detach(&val, NULL), - conf, tr); + conf, + arg_head); } } @@ -1148,6 +1166,16 @@ void free_trailers(struct list_head *trailers) } } +void free_new_trailers(struct list_head *trailers) +{ + struct list_head *pos, *p; + + list_for_each_safe(pos, p, trailers) { + list_del(pos); + free_arg_item(list_entry(pos, struct arg_item, list)); + } +} + size_t trailer_block_start(struct trailer_block *trailer_block) { return trailer_block->start; diff --git a/trailer.h b/trailer.h index d724263e4f6..8fcf1969a3c 100644 --- a/trailer.h +++ b/trailer.h @@ -46,9 +46,20 @@ struct new_trailer_item { enum trailer_if_missing if_missing; }; +void trailer_conf_set(enum trailer_where where, + enum trailer_if_exists if_exists, + enum trailer_if_missing if_missing, + struct trailer_conf *conf); + +struct trailer_conf *new_trailer_conf(void); void duplicate_trailer_conf(struct trailer_conf *dst, const struct trailer_conf *src); +const char *trailer_default_separators(void); + +void trailer_add_arg_item(char *tok, char *val, const struct trailer_conf *conf, + struct list_head *arg_head); + struct process_trailer_options { int in_place; int trim_empty; @@ -95,6 +106,7 @@ void format_trailers(const struct process_trailer_options *opts, struct list_head *trailers, struct strbuf *out); void free_trailers(struct list_head *); +void free_new_trailers(struct list_head *); /* * Convenience function to format the trailers from the commit msg "msg" into From patchwork Wed Jan 31 01:22:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538479 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5A02CA6B for ; Wed, 31 Jan 2024 01:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664158; cv=none; b=k2MBMylzLJA84qFMlUcjp9c8XxrFBVNFspdXphidXsfcOrS9faRlJX2tlg8qoONq11fAtFP9A/5SUu2XLiAl9SWBSV58bUzXlPhwO9BBTCCLv4H/gvY+kJlq3Tugf2nOtMwU6onCimHak9ghTxpfbhuVP4pkj9zkdjolrLeboXM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664158; c=relaxed/simple; bh=bheY8jwd4eNKrHEWKOvW6xsXh6q/pA3jECH3KqCcdVg=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=ogJ/P52xcXzUkzzbYGgfktUfq9IkjVDESpoeYt66Ofjt8RHQe2DUZk3y8dW5/1Y1qLnzhkxAr7nJnnq0bcQZSi9Iah812eAile7loIS2NEnnGnyt8VYF0NRsT9EB+zE2/EtCmrrElJabbSmQZ99GI/0YSwMdBJFrMCilvg/5fZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=axX/0btG; arc=none smtp.client-ip=209.85.128.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="axX/0btG" Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-40fb44a9520so987775e9.1 for ; Tue, 30 Jan 2024 17:22:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664155; x=1707268955; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=Auh6su970Zkwu/bwSWwLWungbSH25XCogQ+HE3bG+iI=; b=axX/0btGBG7VZA5oOxIWSKCpAqW9iW0if5/8xDQBnd/96W3nS6zA64Yn2qSDmusdux 0yjI7h2t3T1r4eeRVD3Nc5+Ih7ckMWxXhjz8mMiR2tM4REYDcvK+0efYlob2O8zrap/5 ktBP09mQAFygJknZNvSoEVIQsBzlIDCiADLhFd01Qw4oIcqOcymwCVVS8wLrFg4jVTng MzeK9iLoqsAVO9W+Lb+pjLjNBbtvaFmQ/tJoFeutNwXh/BWfhPeXc/tmSn1BqAD7QuV5 XTd5lfIfS76ldsegtGMvjnqookrhQdq/NGwlOrw3xPSEu1NTlYLmEf5TN8vzOFzeUeUI n8oQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664155; x=1707268955; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Auh6su970Zkwu/bwSWwLWungbSH25XCogQ+HE3bG+iI=; b=mUE6SVVHfANhQ08WeUPdfr2XVWzQXsax3Dhly9MKlVp6czvX98+HTEHTk/wKo3IqfK kn0CgvObxJcyr491ZEnfhb49B2G8MJhAU87kEdS4rlO4ixH31VG/HYk1MNLwEq7AFOW/ Bnr+15rdn9gen8PQwLGxKW/BfchiLtfImWZuTAxSJINdm/s/5vsFK8mKe/vdUppBi0jE dbitbaFM7UV89OVqjwPYQ65snDMEzzPfkGfmhKcxbFTMN9aisciBVqBIAWHHwqS0Kq7H sqgssX0jVMcwTbkk3f06lS/AiojSZ5KXMo+PUCeEuOf2jQ0yegI27bQQ0ChfHfdXLkdi 6dPQ== X-Gm-Message-State: AOJu0YzVty+7gvbKx7h7m+biFxN4HzGEvXLbHaFT5EXbQXEJ1LvHZCce SCIY4KMg4FK2AWulikPQFdN/l2fr3wFrAlBQ09jLmx/yw0M/wFgL7fd9blLG X-Google-Smtp-Source: AGHT+IGYwUEyJ8jfZ5eo7+Zz5X7tvNg3zJ7yL0bFRD4SJD5Oaur9/N5giM/2lKJHFgiC0VhOSm2uPQ== X-Received: by 2002:a05:600c:314f:b0:40e:4806:f436 with SMTP id h15-20020a05600c314f00b0040e4806f436mr132748wmo.3.1706664155119; Tue, 30 Jan 2024 17:22:35 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e17-20020a05600c4b9100b0040e3bdff98asm50284wmp.23.2024.01.30.17.22.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:34 -0800 (PST) Message-ID: <885ac87a5447e54139171fb3eda62055ffd517cd.1706664145.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:23 +0000 Subject: [PATCH v3 09/10] trailer: delete obsolete argument handling code from API Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver This commit was not squashed with its parent in order to keep the diff separate (to make the additive changes in the parent easier to read). Note that we remove the "new_trailer_item" struct, because it has some overlap with "arg_item" struct that also deals with trailers coming from the command line. The latter will be renamed to "trailer_template" in the next patch. Signed-off-by: Linus Arver --- trailer.c | 39 --------------------------------------- trailer.h | 17 ----------------- 2 files changed, 56 deletions(-) diff --git a/trailer.c b/trailer.c index 19637ff295d..bf1d2eee550 100644 --- a/trailer.c +++ b/trailer.c @@ -744,45 +744,6 @@ void parse_trailers_from_config(struct list_head *config_head) } } -void parse_trailers_from_command_line_args(struct list_head *arg_head, - struct list_head *new_trailer_head) -{ - struct strbuf tok = STRBUF_INIT; - struct strbuf val = STRBUF_INIT; - const struct trailer_conf *conf; - struct list_head *pos; - - /* - * In command-line arguments, '=' is accepted (in addition to the - * separators that are defined). - */ - char *cl_separators = xstrfmt("=%s", separators); - - /* Add an arg item for each trailer on the command line */ - list_for_each(pos, new_trailer_head) { - struct new_trailer_item *tr = - list_entry(pos, struct new_trailer_item, list); - ssize_t separator_pos = find_separator(tr->text, cl_separators); - - if (separator_pos == 0) { - struct strbuf sb = STRBUF_INIT; - strbuf_addstr(&sb, tr->text); - strbuf_trim(&sb); - error(_("empty trailer token in trailer '%.*s'"), - (int) sb.len, sb.buf); - strbuf_release(&sb); - } else { - parse_trailer(tr->text, separator_pos, &tok, &val, &conf); - trailer_add_arg_item(strbuf_detach(&tok, NULL), - strbuf_detach(&val, NULL), - conf, - arg_head); - } - } - - free(cl_separators); -} - static const char *next_line(const char *str) { const char *nl = strchrnul(str, '\n'); diff --git a/trailer.h b/trailer.h index 8fcf1969a3c..5d4bacd9931 100644 --- a/trailer.h +++ b/trailer.h @@ -32,20 +32,6 @@ int trailer_set_where(enum trailer_where *item, const char *value); int trailer_set_if_exists(enum trailer_if_exists *item, const char *value); int trailer_set_if_missing(enum trailer_if_missing *item, const char *value); -/* - * A list that represents newly-added trailers, such as those provided - * with the --trailer command line option of git-interpret-trailers. - */ -struct new_trailer_item { - struct list_head list; - - const char *text; - - enum trailer_where where; - enum trailer_if_exists if_exists; - enum trailer_if_missing if_missing; -}; - void trailer_conf_set(enum trailer_where where, enum trailer_if_exists if_exists, enum trailer_if_missing if_missing, @@ -79,9 +65,6 @@ struct process_trailer_options { void parse_trailers_from_config(struct list_head *config_head); -void parse_trailers_from_command_line_args(struct list_head *arg_head, - struct list_head *new_trailer_head); - void process_trailers_lists(struct list_head *head, struct list_head *arg_head); From patchwork Wed Jan 31 01:22:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver X-Patchwork-Id: 13538480 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2075EAE4 for ; Wed, 31 Jan 2024 01:22:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664161; cv=none; b=OfWz3TjTBQ0UNONvqFTyBlXsNdCm6pJoPKmuJ18vkVIvj+clrgiczQ0K/OZMdrK0rsr9TCQfzJu+x3vq1Wwc8aWi3241Uck0SYb2PZpP9XNFTTGhADe0MGEcWb1Wxk7+XivGzaKnyYManfUMT52n43kevNtH54AjPPakiBVnCoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706664161; c=relaxed/simple; bh=W+QEYGK5Ztlupean4dGYQXt1thkWgmfwzcyDFvoxn1I=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=nraAuwEdsQzfPV0x0U7MqrQQ4fOJm+GRyPj76S//Dn+fX2ydVV3MNF//r5UkT5SKrEfQXIYkYEGEl01Mz1yYe0ZnoMRToHEEmUV+/pBJhF25IoUd0aXypkDQ6iCyLYsjgTfWSFqZGWGaO40rICVmDuCRLtBF696AeyPTdZ5tM/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QXbZY5iI; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QXbZY5iI" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-40fb0c4bb9fso4581415e9.0 for ; Tue, 30 Jan 2024 17:22:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706664156; x=1707268956; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=eYLaSo1h9hYN8zK+VxBMhTMfsDF6KI3Kl7hyVo+MjZg=; b=QXbZY5iICih0mffV4ecoB0cXBXBJ71xWpvW39CC5UhcGIfG5q9Utx/UXAr1WMhe880 fmd/Nc8dIWEFoHy2M1hUZlEMY5KH2EvibpziMd7h1I6rFfra9r/tW6MTxCXf5VxA/p5d Bo+kJHRbYG8d31qF/rEs9xu7M+WCHlL+qA1T4lJr3jEuFljVfmxmIcO/1XJEgcCyJNWS 1GPRJ+eBK9Y0aVOTuyDZ+3naei0GYvU8AQ/gxQgGIaG/jkROUIf38zVyhdeK6GhuU/Pc cAEna5Xa9p2bPaoRssVR2jGycRnK2PC1JAi3Wo1ZlF46gZg62cM+PgOVAsiOxVSr1/Xt IQng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706664156; x=1707268956; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eYLaSo1h9hYN8zK+VxBMhTMfsDF6KI3Kl7hyVo+MjZg=; b=Bnw4OWEk5ZRGzA5yWLcpt/Gf/RsctRtsTl4JUlCBGaQ1CivdOaMjqH69/AWJhao6ub c45BSa3Jj79tqqZMppFtk2fdFmkBe4KFrn6+h7I6QhvG3ADxrmISOpfBeYfKIVdj0AUo uOst8+yS57nbxOXdgTrgK8abhpjVDWBlMLbbhSUXiY7UZ1kaZnTSndN4dJpk4yF7wt7+ y0q6sS8WqoA3SYtESn439vFuoqQ4BRG1uFr+oDKJLqSOkd6z9r8VTRPqBqZcY86BLzyj g9qPHhnrHr5bQboH1IBjyeGGI+VkDxGb0t7l2n3jWK3s9vFJ7EES6ko6B0s81ThlOh+q /ukw== X-Gm-Message-State: AOJu0YxpOhmBxTefZGZLoz+0YCN8QHNn/t1Yd/psq/A7F0j0tZLdTGTM 9hgCuSA6UO2kqTiZpmYivTL54lNa1m2L5WtWZTljib5cyasjA7jvsTSFmUvm X-Google-Smtp-Source: AGHT+IE01vN8Qnq7e61dh3Rb8Kw5a3FXD87ROMZbDGFPrBQdfMWezzfidPP6/wp3tRM9MWsB73ae6Q== X-Received: by 2002:a05:600c:2a16:b0:40f:b336:212 with SMTP id w22-20020a05600c2a1600b0040fb3360212mr140133wme.18.1706664155843; Tue, 30 Jan 2024 17:22:35 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id jr7-20020a05600c560700b0040efa513540sm45291wmb.22.2024.01.30.17.22.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 17:22:35 -0800 (PST) Message-ID: In-Reply-To: References: Date: Wed, 31 Jan 2024 01:22:24 +0000 Subject: [PATCH v3 10/10] trailer: introduce "template" term for readability Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Junio C Hamano , Emily Shaffer , Josh Steadmon , "Randall S. Becker" , Linus Arver , Linus Arver From: Linus Arver From: Linus Arver The term "arg_item" is ambiguous because we use it to hold data for (1) trailers specified as command line arguments (in builtin/interpret-trailers.c), and (2) trailers specified in configuration, and these are both used to ultimately insert new trailers (based on the contents of arg_item, acting as a kind of template) into some other set of existing trailers (such as those found in a trailer block inside a log message) that have already been parsed. Rename "arg_item" to "trailer_template". This necessitates further renames to make the functions that act on these templates match the data structures (parameters) they act on: - [*] add_arg_to_input_list() to apply_template_to_trailers() - [*] apply_arg_if_exists() to maybe_add_if_exists() - [*] apply_arg_if_missing() to maybe_add_if_missing() - apply_command() to run_command_from_template() - [*] apply_item_command() to populate_template_value() - free_arg_item() to free_template() (non-API function) - free_new_trailers() to free_trailer_templates() (API function) - get_conf_item() to get_or_add_template_by() - option_parse_trailer() to option_parse_trailer_template() - parse_trailers_from_config() to parse_trailer_templates_from_config() - [*] process_trailers_lists() to apply_trailer_templates() - token_from_item() to token_from_template() - token_matches_item to token_matches_template - [*] trailer_add_arg_item() to add_trailer_template() - trailer_from_arg() to trailer_from() - [*] check_if_different() (reorder parameters only) - [*] find_same_and_apply_arg() (reorder parameters only) Reorder parameters where appropriate; these functions have been marked with an asterisk ([*]). This removes the "arg" terminology (standing for "CLI arguments") from the trailer implementation, which makes sense because trailers themselves have nothing to do with CLI argument handling. Also note that these renames expose the previously liberal use of "trailer" to mean both trailers we read from the input text (trailer block) and trailer templates that are defined as CLI args or configurations. Some functions implied a single action when they could do two different things, so introduce words like "maybe" and "or" to unmask their behavior. In summary this patch renames and reorders parameters for readability, without any behavioral change. We don't rename find_same_and_apply_arg(), because it will be refactored soon. As an added benefit, we no longer use the term "arg" to mean "CLI arguments" in the trailer implementation, because trailers themselves should not be concerned about CLI arguments (this is the domain of the interpret-trailers builtin). For parse_trailers_from_config() (renamed to parse_trailer_templates_from_config()), add a NEEDSWORK discussion about how the deprecated trailer.*.command configuration option is oddly more featureful than trailer.*.cmd (if we were to remove support for trailer.*.command, users would not be able to replicate the behavior with trailer.*.cmd and lose out on functionality). Signed-off-by: Linus Arver --- builtin/interpret-trailers.c | 48 +++--- trailer.c | 292 +++++++++++++++++++---------------- trailer.h | 11 +- 3 files changed, 192 insertions(+), 159 deletions(-) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 9a902012912..aae3f3119df 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -47,10 +47,14 @@ static int option_parse_if_missing(const struct option *opt, static char *cl_separators; -static int option_parse_trailer(const struct option *opt, - const char *arg, int unset) +/* + * Interpret "--trailer ..." as trailer templates (trailers we want to add into + * the input text). + */ +static int option_parse_trailer_template(const struct option *opt, + const char *arg, int unset) { - struct list_head *trailers = opt->value; + struct list_head *templates = opt->value; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; const struct trailer_conf *conf; @@ -58,7 +62,7 @@ static int option_parse_trailer(const struct option *opt, ssize_t separator_pos; if (unset) { - free_new_trailers(trailers); + free_trailer_templates(templates); return 0; } @@ -75,10 +79,10 @@ static int option_parse_trailer(const struct option *opt, */ trailer_conf_set(where, if_exists, if_missing, conf_current); - trailer_add_arg_item(strbuf_detach(&tok, NULL), + add_trailer_template(strbuf_detach(&tok, NULL), strbuf_detach(&val, NULL), conf_current, - trailers); + templates); } else { struct strbuf sb = STRBUF_INIT; strbuf_addstr(&sb, arg); @@ -148,10 +152,10 @@ static void read_input_file(struct strbuf *sb, const char *file) } static void interpret_trailers(const struct process_trailer_options *opts, - struct list_head *arg_trailers, + struct list_head *templates, const char *file) { - LIST_HEAD(head); + LIST_HEAD(trailers_from_sb); struct strbuf sb = STRBUF_INIT; struct strbuf tb = STRBUF_INIT; struct trailer_block *trailer_block; @@ -162,7 +166,7 @@ static void interpret_trailers(const struct process_trailer_options *opts, if (opts->in_place) outfile = create_in_place_tempfile(file); - trailer_block = parse_trailers(opts, sb.buf, &head); + trailer_block = parse_trailers(opts, sb.buf, &trailers_from_sb); /* Print the lines before the trailer block */ if (!opts->only_trailers) @@ -173,15 +177,15 @@ static void interpret_trailers(const struct process_trailer_options *opts, if (!opts->only_input) { - process_trailers_lists(&head, arg_trailers); + apply_trailer_templates(templates, &trailers_from_sb); } /* Print trailer block. */ - format_trailers(opts, &head, &tb); + format_trailers(opts, &trailers_from_sb, &tb); fwrite(tb.buf, 1, tb.len, outfile); strbuf_release(&tb); - free_trailers(&head); + free_trailers(&trailers_from_sb); /* Print the lines after the trailer block as is */ if (!opts->only_trailers) @@ -199,8 +203,8 @@ static void interpret_trailers(const struct process_trailer_options *opts, int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; - LIST_HEAD(configured_trailers); - LIST_HEAD(arg_trailers); + LIST_HEAD(configured_templates); + LIST_HEAD(templates); struct option options[] = { OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")), @@ -219,8 +223,8 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) OPT_CALLBACK_F(0, "parse", &opts, NULL, N_("alias for --only-trailers --only-input --unfold"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse), OPT_BOOL(0, "no-divider", &opts.no_divider, N_("do not treat \"---\" as the end of input")), - OPT_CALLBACK(0, "trailer", &arg_trailers, N_("trailer"), - N_("trailer(s) to add"), option_parse_trailer), + OPT_CALLBACK(0, "trailer", &templates, N_("trailer"), + N_("trailer(s) to add"), option_parse_trailer_template), OPT_END() }; @@ -228,7 +232,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) trailer_config_init(); if (!opts.only_input) { - parse_trailers_from_config(&configured_trailers); + parse_trailer_templates_from_config(&configured_templates); } /* @@ -242,25 +246,25 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) free(cl_separators); - if (opts.only_input && !list_empty(&arg_trailers)) + if (opts.only_input && !list_empty(&templates)) usage_msg_opt( _("--trailer with --only-input does not make sense"), git_interpret_trailers_usage, options); - list_splice(&configured_trailers, &arg_trailers); + list_splice(&configured_templates, &templates); if (argc) { int i; for (i = 0; i < argc; i++) - interpret_trailers(&opts, &arg_trailers, argv[i]); + interpret_trailers(&opts, &templates, argv[i]); } else { if (opts.in_place) die(_("no input file given for in-place editing")); - interpret_trailers(&opts, &arg_trailers, NULL); + interpret_trailers(&opts, &templates, NULL); } - free_new_trailers(&arg_trailers); + free_trailer_templates(&templates); return 0; } diff --git a/trailer.c b/trailer.c index bf1d2eee550..a739e2ada86 100644 --- a/trailer.c +++ b/trailer.c @@ -55,14 +55,14 @@ struct trailer_item { char *value; }; -struct arg_item { +struct trailer_template { struct list_head list; char *token; char *value; struct trailer_conf conf; }; -static LIST_HEAD(conf_head); +static LIST_HEAD(templates_from_conf); static char *separators = ":"; @@ -105,7 +105,7 @@ static size_t token_len_without_separator(const char *token, size_t len) return len; } -static int same_token(struct trailer_item *a, struct arg_item *b) +static int same_token(struct trailer_item *a, struct trailer_template *b) { size_t a_len, b_len, min_len; @@ -119,12 +119,12 @@ static int same_token(struct trailer_item *a, struct arg_item *b) return !strncasecmp(a->token, b->token, min_len); } -static int same_value(struct trailer_item *a, struct arg_item *b) +static int same_value(struct trailer_item *a, struct trailer_template *b) { return !strcasecmp(a->value, b->value); } -static int same_trailer(struct trailer_item *a, struct arg_item *b) +static int same_trailer(struct trailer_item *a, struct trailer_template *b) { return same_token(a, b) && same_value(a, b); } @@ -151,15 +151,15 @@ static void free_trailer_item(struct trailer_item *item) free(item); } -static void free_arg_item(struct arg_item *item) +static void free_template(struct trailer_template *template) { - free(item->conf.name); - free(item->conf.key); - free(item->conf.command); - free(item->conf.cmd); - free(item->token); - free(item->value); - free(item); + free(template->conf.name); + free(template->conf.key); + free(template->conf.command); + free(template->conf.cmd); + free(template->token); + free(template->value); + free(template); } static char last_non_space_char(const char *s) @@ -171,36 +171,36 @@ static char last_non_space_char(const char *s) return '\0'; } -static struct trailer_item *trailer_from_arg(struct arg_item *arg_tok) +static struct trailer_item *trailer_from(struct trailer_template *template) { struct trailer_item *new_item = xcalloc(1, sizeof(*new_item)); - new_item->token = arg_tok->token; - new_item->value = arg_tok->value; - arg_tok->token = arg_tok->value = NULL; - free_arg_item(arg_tok); + new_item->token = template->token; + new_item->value = template->value; + template->token = template->value = NULL; + free_template(template); return new_item; } -static void add_arg_to_input_list(struct trailer_item *on_tok, - struct arg_item *arg_tok) +static void apply_template_to_trailers(struct trailer_template *template, + struct trailer_item *on_tok) { - int aoe = after_or_end(arg_tok->conf.where); - struct trailer_item *to_add = trailer_from_arg(arg_tok); + int aoe = after_or_end(template->conf.where); + struct trailer_item *to_add = trailer_from(template); if (aoe) list_add(&to_add->list, &on_tok->list); else list_add_tail(&to_add->list, &on_tok->list); } -static int check_if_different(struct trailer_item *in_tok, - struct arg_item *arg_tok, - int check_all, - struct list_head *head) +static int check_if_different(struct trailer_template *template, + struct trailer_item *in_tok, + struct list_head *head, + int check_all) { - enum trailer_where where = arg_tok->conf.where; + enum trailer_where where = template->conf.where; struct list_head *next_head; do { - if (same_trailer(in_tok, arg_tok)) + if (same_trailer(in_tok, template)) return 0; /* * if we want to add a trailer after another one, @@ -215,7 +215,8 @@ static int check_if_different(struct trailer_item *in_tok, return 1; } -static char *apply_command(struct trailer_conf *conf, const char *arg) +static char *run_command_from_template(struct trailer_conf *conf, + const char *arg) { struct strbuf cmd = STRBUF_INIT; struct strbuf buf = STRBUF_INIT; @@ -250,133 +251,142 @@ static char *apply_command(struct trailer_conf *conf, const char *arg) return result; } -static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok) +/* + * Prepare the template by running the command (if any) requested by the + * template in order to populate the template's value field. + */ +static void populate_template_value(struct trailer_template *template, + struct trailer_item *in_tok) { - if (arg_tok->conf.command || arg_tok->conf.cmd) { + if (template->conf.command || template->conf.cmd) { + /* + * Determine argument to pass into the command. + */ const char *arg; - if (arg_tok->value && arg_tok->value[0]) { - arg = arg_tok->value; + if (template->value && template->value[0]) { + arg = template->value; } else { if (in_tok && in_tok->value) arg = xstrdup(in_tok->value); else arg = xstrdup(""); } - arg_tok->value = apply_command(&arg_tok->conf, arg); + template->value = run_command_from_template(&template->conf, + arg); free((char *)arg); } } -static void apply_arg_if_exists(struct trailer_item *in_tok, - struct arg_item *arg_tok, +static void maybe_add_if_exists(struct trailer_template *template, + struct trailer_item *in_tok, struct trailer_item *on_tok, - struct list_head *head) + struct list_head *trailers) { - switch (arg_tok->conf.if_exists) { + switch (template->conf.if_exists) { case EXISTS_DO_NOTHING: - free_arg_item(arg_tok); + free_template(template); break; case EXISTS_REPLACE: - apply_item_command(in_tok, arg_tok); - add_arg_to_input_list(on_tok, arg_tok); + populate_template_value(template, in_tok); + apply_template_to_trailers(template, on_tok); list_del(&in_tok->list); free_trailer_item(in_tok); break; case EXISTS_ADD: - apply_item_command(in_tok, arg_tok); - add_arg_to_input_list(on_tok, arg_tok); + populate_template_value(template, in_tok); + apply_template_to_trailers(template, on_tok); break; case EXISTS_ADD_IF_DIFFERENT: - apply_item_command(in_tok, arg_tok); - if (check_if_different(in_tok, arg_tok, 1, head)) - add_arg_to_input_list(on_tok, arg_tok); + populate_template_value(template, in_tok); + if (check_if_different(template, in_tok, trailers, 1)) + apply_template_to_trailers(template, on_tok); else - free_arg_item(arg_tok); + free_template(template); break; case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR: - apply_item_command(in_tok, arg_tok); - if (check_if_different(on_tok, arg_tok, 0, head)) - add_arg_to_input_list(on_tok, arg_tok); + populate_template_value(template, in_tok); + if (check_if_different(template, on_tok, trailers, 0)) + apply_template_to_trailers(template, on_tok); else - free_arg_item(arg_tok); + free_template(template); break; default: BUG("trailer.c: unhandled value %d", - arg_tok->conf.if_exists); + template->conf.if_exists); } } -static void apply_arg_if_missing(struct list_head *head, - struct arg_item *arg_tok) +static void maybe_add_if_missing(struct trailer_template *template, + struct list_head *trailers) { enum trailer_where where; struct trailer_item *to_add; - switch (arg_tok->conf.if_missing) { + switch (template->conf.if_missing) { case MISSING_DO_NOTHING: - free_arg_item(arg_tok); + free_template(template); break; case MISSING_ADD: - where = arg_tok->conf.where; - apply_item_command(NULL, arg_tok); - to_add = trailer_from_arg(arg_tok); + where = template->conf.where; + populate_template_value(template, NULL); + to_add = trailer_from(template); if (after_or_end(where)) - list_add_tail(&to_add->list, head); + list_add_tail(&to_add->list, trailers); else - list_add(&to_add->list, head); + list_add(&to_add->list, trailers); break; default: BUG("trailer.c: unhandled value %d", - arg_tok->conf.if_missing); + template->conf.if_missing); } } -static int find_same_and_apply_arg(struct list_head *head, - struct arg_item *arg_tok) +static int find_same_and_apply_arg(struct trailer_template *template, + struct list_head *trailers) { struct list_head *pos; struct trailer_item *in_tok; struct trailer_item *on_tok; - enum trailer_where where = arg_tok->conf.where; + enum trailer_where where = template->conf.where; int middle = (where == WHERE_AFTER) || (where == WHERE_BEFORE); int backwards = after_or_end(where); struct trailer_item *start_tok; - if (list_empty(head)) + if (list_empty(trailers)) return 0; - start_tok = list_entry(backwards ? head->prev : head->next, + start_tok = list_entry(backwards ? trailers->prev : trailers->next, struct trailer_item, list); - list_for_each_dir(pos, head, backwards) { + list_for_each_dir(pos, trailers, backwards) { in_tok = list_entry(pos, struct trailer_item, list); - if (!same_token(in_tok, arg_tok)) + if (!same_token(in_tok, template)) continue; on_tok = middle ? in_tok : start_tok; - apply_arg_if_exists(in_tok, arg_tok, on_tok, head); + maybe_add_if_exists(template, in_tok, on_tok, trailers); return 1; } return 0; } -void process_trailers_lists(struct list_head *head, - struct list_head *arg_head) +void apply_trailer_templates(struct list_head *templates, + struct list_head *trailers) { struct list_head *pos, *p; - struct arg_item *arg_tok; + struct trailer_template *template; - list_for_each_safe(pos, p, arg_head) { + list_for_each_safe(pos, p, templates) { int applied = 0; - arg_tok = list_entry(pos, struct arg_item, list); + template = list_entry(pos, struct trailer_template, list); list_del(pos); - applied = find_same_and_apply_arg(head, arg_tok); + applied = find_same_and_apply_arg(template, trailers); if (!applied) - apply_arg_if_missing(head, arg_tok); + maybe_add_if_missing(template, trailers); } } @@ -458,26 +468,26 @@ void duplicate_trailer_conf(struct trailer_conf *dst, dst->cmd = xstrdup_or_null(src->cmd); } -static struct arg_item *get_conf_item(const char *name) +static struct trailer_template *get_or_add_template_by(const char *name) { struct list_head *pos; - struct arg_item *item; + struct trailer_template *template; - /* Look up item with same name */ - list_for_each(pos, &conf_head) { - item = list_entry(pos, struct arg_item, list); - if (!strcasecmp(item->conf.name, name)) - return item; + /* Look up template with same name. */ + list_for_each(pos, &templates_from_conf) { + template = list_entry(pos, struct trailer_template, list); + if (!strcasecmp(template->conf.name, name)) + return template; } - /* Item does not already exists, create it */ - CALLOC_ARRAY(item, 1); - duplicate_trailer_conf(&item->conf, &default_trailer_conf); - item->conf.name = xstrdup(name); + /* Template does not already exist; create it. */ + CALLOC_ARRAY(template, 1); + duplicate_trailer_conf(&template->conf, &default_trailer_conf); + template->conf.name = xstrdup(name); - list_add_tail(&item->list, &conf_head); + list_add_tail(&template->list, &templates_from_conf); - return item; + return template; } enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_CMD, @@ -535,7 +545,7 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb UNUSED) { const char *trailer_item, *variable_name; - struct arg_item *item; + struct trailer_template *template; struct trailer_conf *conf; char *name = NULL; enum trailer_info_type type; @@ -560,8 +570,8 @@ static int git_trailer_config(const char *conf_key, const char *value, if (!name) return 0; - item = get_conf_item(name); - conf = &item->conf; + template = get_or_add_template_by(name); + conf = &template->conf; free(name); switch (type) { @@ -618,20 +628,22 @@ void trailer_config_init(void) configured = 1; } -static const char *token_from_item(struct arg_item *item, char *tok) +static const char *token_from_template(struct trailer_template *template, char *tok) { - if (item->conf.key) - return item->conf.key; + if (template->conf.key) + return template->conf.key; if (tok) return tok; - return item->conf.name; + return template->conf.name; } -static int token_matches_item(const char *tok, struct arg_item *item, size_t tok_len) +static int token_matches_template(const char *tok, + struct trailer_template *template, + size_t tok_len) { - if (!strncasecmp(tok, item->conf.name, tok_len)) + if (!strncasecmp(tok, template->conf.name, tok_len)) return 1; - return item->conf.key ? !strncasecmp(tok, item->conf.key, tok_len) : 0; + return template->conf.key ? !strncasecmp(tok, template->conf.key, tok_len) : 0; } /* @@ -677,7 +689,7 @@ void parse_trailer(const char *line, ssize_t separator_pos, struct strbuf *tok, struct strbuf *val, const struct trailer_conf **conf) { - struct arg_item *item; + struct trailer_template *template; size_t tok_len; struct list_head *pos; @@ -695,13 +707,13 @@ void parse_trailer(const char *line, ssize_t separator_pos, tok_len = token_len_without_separator(tok->buf, tok->len); if (conf) *conf = &default_trailer_conf; - list_for_each(pos, &conf_head) { - item = list_entry(pos, struct arg_item, list); - if (token_matches_item(tok->buf, item, tok_len)) { + list_for_each(pos, &templates_from_conf) { + template = list_entry(pos, struct trailer_template, list); + if (token_matches_template(tok->buf, template, tok_len)) { char *tok_buf = strbuf_detach(tok, NULL); if (conf) - *conf = &item->conf; - strbuf_addstr(tok, token_from_item(item, tok_buf)); + *conf = &template->conf; + strbuf_addstr(tok, token_from_template(template, tok_buf)); free(tok_buf); break; } @@ -718,29 +730,41 @@ static struct trailer_item *add_trailer_item(struct list_head *head, char *tok, return new_item; } -void trailer_add_arg_item(char *tok, char *val, const struct trailer_conf *conf, - struct list_head *arg_head) +void add_trailer_template(char *tok, char *val, const struct trailer_conf *conf, + struct list_head *templates) { - struct arg_item *new_item = xcalloc(1, sizeof(*new_item)); - new_item->token = tok; - new_item->value = val; - duplicate_trailer_conf(&new_item->conf, conf); - list_add_tail(&new_item->list, arg_head); + struct trailer_template *template = xcalloc(1, sizeof(*template)); + template->token = tok; + template->value = val; + duplicate_trailer_conf(&template->conf, conf); + list_add_tail(&template->list, templates); } -void parse_trailers_from_config(struct list_head *config_head) +void parse_trailer_templates_from_config(struct list_head *config_head) { - struct arg_item *item; + struct trailer_template *template; struct list_head *pos; - /* Add an arg item for each configured trailer with a command */ - list_for_each(pos, &conf_head) { - item = list_entry(pos, struct arg_item, list); - if (item->conf.command) - trailer_add_arg_item(xstrdup(token_from_item(item, NULL)), - xstrdup(""), - &item->conf, - config_head); + /* + * Get configured templates with a ".command" option. + * + * NEEDSWORK: If the interpret-trailers builtin sees a + * "trailer.foo.command = ..." setting, then the "foo" trailer will + * always be inserted, even if "--trailer foo" is not provided. + * Considering how ".command" is deprecated, it is a bit strange to see + * it getting special treatment like this over ".cmd". Instead, we + * should add a new option that explicitly lets the user decide if the + * configured trailer should always be added automatically, or if it + * should only be added if "--trailer foo" is provided (default). + * Then we can collect configured trailers that have either ".command" + * or ".cmd" below, instead of just ".command". + */ + list_for_each(pos, &templates_from_conf) { + template = list_entry(pos, struct trailer_template, list); + if (template->conf.command) + add_trailer_template(xstrdup(token_from_template(template, + NULL)), + xstrdup(""), &template->conf, config_head); } } @@ -852,7 +876,7 @@ static size_t find_trailer_block_start(const char *buf, size_t len) * Get the start of the trailers by looking starting from the end for a * blank line before a set of non-blank lines that (i) are all * trailers, or (ii) contains at least one Git-generated trailer and - * consists of at least 25% trailers. + * consists of at least 25% configured trailers. */ for (l = last_line(buf, len); l >= end_of_title; @@ -896,10 +920,16 @@ static size_t find_trailer_block_start(const char *buf, size_t len) possible_continuation_lines = 0; if (recognized_prefix) continue; - list_for_each(pos, &conf_head) { - struct arg_item *item; - item = list_entry(pos, struct arg_item, list); - if (token_matches_item(bol, item, + /* + * The templates here are not used for actually + * adding trailers anywhere, but instead to help us + * identify trailer lines by comparing their keys with + * those found in configured templates. + */ + list_for_each(pos, &templates_from_conf) { + struct trailer_template *template; + template = list_entry(pos, struct trailer_template, list); + if (token_matches_template(bol, template, separator_pos)) { recognized_prefix = 1; break; @@ -1127,13 +1157,13 @@ void free_trailers(struct list_head *trailers) } } -void free_new_trailers(struct list_head *trailers) +void free_trailer_templates(struct list_head *trailer_templates) { struct list_head *pos, *p; - list_for_each_safe(pos, p, trailers) { + list_for_each_safe(pos, p, trailer_templates) { list_del(pos); - free_arg_item(list_entry(pos, struct arg_item, list)); + free_template(list_entry(pos, struct trailer_template, list)); } } diff --git a/trailer.h b/trailer.h index 5d4bacd9931..79aa123478d 100644 --- a/trailer.h +++ b/trailer.h @@ -43,8 +43,8 @@ void duplicate_trailer_conf(struct trailer_conf *dst, const char *trailer_default_separators(void); -void trailer_add_arg_item(char *tok, char *val, const struct trailer_conf *conf, - struct list_head *arg_head); +void add_trailer_template(char *tok, char *val, const struct trailer_conf *conf, + struct list_head *templates); struct process_trailer_options { int in_place; @@ -63,10 +63,9 @@ struct process_trailer_options { #define PROCESS_TRAILER_OPTIONS_INIT {0} -void parse_trailers_from_config(struct list_head *config_head); +void parse_trailer_templates_from_config(struct list_head *config_head); -void process_trailers_lists(struct list_head *head, - struct list_head *arg_head); +void apply_trailer_templates(struct list_head *templates, struct list_head *trailers_head); ssize_t find_separator(const char *line, const char *separators); @@ -89,7 +88,7 @@ void format_trailers(const struct process_trailer_options *opts, struct list_head *trailers, struct strbuf *out); void free_trailers(struct list_head *); -void free_new_trailers(struct list_head *); +void free_trailer_templates(struct list_head *); /* * Convenience function to format the trailers from the commit msg "msg" into