From patchwork Sun May 5 18:49:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Passaro X-Patchwork-Id: 13654616 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.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 85BA225745 for ; Sun, 5 May 2024 18:49:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714934957; cv=none; b=nFe/S9YSmn3+Ameo+My/ImleV+gwcIPQU5Bbne4OYJBOPjZXRXa8V8zK5WLx4DIVl8+CZM2rvRBIfmCn9Hnjzi/PRymbwpF22WrbxzWPVWig0pCtt788J/9tUPWuSFbB0Up+NuEhk0Rhvgdv51eK1H4MCTPDeFJOzqei45NC9Tk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714934957; c=relaxed/simple; bh=4NCWFMtRTPSIc86cPymWZlO2yuHrOPCwq5qO4PxqK1A=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=ZX9JLluPyfVehttwKxGVXu3HHOSZ5t5dRMQfYy1Nv/PzvUxJ+ILPMt0Kqe4Sd0GLcv0agGrghQoIwNdY3HPvsbHyzaxJlqtfLtUokogVa5XN7iOcCojCJucRKWFTpWdSP4YBmIZuAjYu+c53IHapzl9Te4qBpcEm7QpqXUQK5e0= 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=lUHeUcjW; arc=none smtp.client-ip=209.85.128.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="lUHeUcjW" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-41b782405bbso8549395e9.1 for ; Sun, 05 May 2024 11:49:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1714934953; x=1715539753; 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=MKCG2dO8zAqMC/M1isHJqVhqlH5cCUVS7CzSAHkfNoE=; b=lUHeUcjW6RD9a8iCjRPfTdf4pucEGH9eeFY49IA0WE3Y6B7aMdzFwdbLRePa7+E/7w Xkfnxbu8CAIYMHfj1dFsyMRkTALeLSPkpWgSR3uvR1hz1XZBz/ZALifxivQGSUW7Xtxr fzi5G9Qf2TMI7PB0LfRWyPaCKzomM+UC/mOPViUTDX2Byvy9NmSsEKo1pYQ18GO7jHQj 24M53EG3qu1kZ6qvN2uR/3yuwc3SlhnbGl2rLWe6Dm1p3Ht1EWJE1+XK4aMlnksMHbFB nkgyBXMuq8LGFRNahj+EYGGRDHk7vG0cwVbWMsJqwaQK50z/6oV11eElNKfxv2K5r+ll 98Ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714934953; x=1715539753; 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=MKCG2dO8zAqMC/M1isHJqVhqlH5cCUVS7CzSAHkfNoE=; b=VJxUg2sNZGQAlA7VunrgJ0weSTs0kGX4BtA28lyT2lGzsMG7RytDl4ljjVWQ1Hjddg YQm/Z459I7ec1l6fuXBlf8AYQhl07wZkU5Dc23E2FO9LNKA7i+9Ruli1QNkxy+jrhAsp 0fvo2vvT+/wvbSdNllnH6YVME4WXnlbrq7nxtlkpQgYuWyY79ajmJ8KR9rFROVgC92Lm aQ4MU5KT43cy69WoEbqhMK8prQsb9OzhKJsMoSISAcjJ8+wyIxF3axKHZVsdXaEPh8LT 6ZjT8Jcble/53f/Mu0C2m/To50ir5oQghsgF246DuAmCPNXP0oA5bRTRg5UOUwlsdxZT GfOQ== X-Gm-Message-State: AOJu0Yw9AmYiQYAXgcqNI8IH1A04cQGB1o7c/D3Oz3jhX63Snypd2W9u ryHDR/+KhTbuzooUeQIhjbiuM0fWa6wGm+Z2YuJLXxkQ4hqxPHjvVE2Fyw== X-Google-Smtp-Source: AGHT+IEYM3bJKLvIrxPdLpOQfY7grKcO9YGpfzOCYY22Sm5achca1cuotgV12w5P28pcbaUn9dNisQ== X-Received: by 2002:a05:600c:4f81:b0:419:f3f9:8ee3 with SMTP id n1-20020a05600c4f8100b00419f3f98ee3mr5553579wmq.5.1714934953466; Sun, 05 May 2024 11:49:13 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id fm9-20020a05600c0c0900b0041c23148330sm17113508wmb.10.2024.05.05.11.49.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 May 2024 11:49:13 -0700 (PDT) Message-Id: <85f45a57f3529a90324ded07856fca610f7b5eda.1714934950.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sun, 05 May 2024 18:49:08 +0000 Subject: [PATCH v5 1/3] builtin/commit: use ARGV macro to collect trailers 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: Junio C Hamano , Patrick Steinhardt , John Passaro , John Passaro , John Passaro From: John Passaro From: John Passaro Replace git-commit's callback for --trailer with the standard OPT_PASSTHRU_ARGV macro. The callback only adds its values to a strvec and sanity-checking that `unset` is always false; both of these are already implemented in the parse-option API. Signed-off-by: John Passaro --- builtin/commit.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/builtin/commit.c b/builtin/commit.c index 6e1484446b0..5a3248370db 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -142,14 +142,6 @@ static struct strbuf message = STRBUF_INIT; static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED; -static int opt_pass_trailer(const struct option *opt, const char *arg, int unset) -{ - BUG_ON_OPT_NEG(unset); - - strvec_pushl(opt->value, "--trailer", arg, NULL); - return 0; -} - static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset) { enum wt_status_format *value = (enum wt_status_format *)opt->value; @@ -1673,7 +1665,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) OPT_STRING(0, "fixup", &fixup_message, N_("[(amend|reword):]commit"), N_("use autosquash formatted message to fixup or amend/reword specified commit")), OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")), OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")), - OPT_CALLBACK_F(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG, opt_pass_trailer), + OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG), OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")), OPT_FILENAME('t', "template", &template_file, N_("use specified template file")), OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")), From patchwork Sun May 5 18:49:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Passaro X-Patchwork-Id: 13654617 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.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 C9B2C5CDD0 for ; Sun, 5 May 2024 18:49:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714934958; cv=none; b=LRToq2kZ3vps99apQgp0T7H6lEgpTb1tnXqT9Troz9Z2qr/MGVlKtrtqnCJf5Glf842Iw22PbEmud1w26beQLIIPXspQzLc1JBvRg0DBCd7r/JOyxenKewPvTjM9t6MkJaF/QH27mOeLnh3g64lRSul4uR0mUyGyoEtOZJ70AzE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714934958; c=relaxed/simple; bh=3fGxmYysPqcjv7xKBtDFgJfOXVE0AMuDpRMlpbMXXpg=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=NUgpullM5HpVVNXqRyMTYsggBCLEwa+rw/ivjpFqG6vv+0XamUZFWIVq1HnPJe1695c+yqYSTOQCxbi20Hgh+qxBdVEC8ARDkNT9i3lEB+MDoY+QSIfxShv1wnvkwiObXuzPCMR+4p1sdeRLU8C21qzDPbOnRlLMYMfMN2XO0gk= 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=iL8ghEBY; arc=none smtp.client-ip=209.85.128.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="iL8ghEBY" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-41b9dff6be8so8146895e9.3 for ; Sun, 05 May 2024 11:49:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1714934955; x=1715539755; 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=fBm6oxPeCoNnW1L+QveNHU22NEffJtQvwuNSrI9Hc6w=; b=iL8ghEBY9Ck5T0lYzIA246bgamn5Q8oD1ICSgC6ZuaW/LyBVCXaEdhs1/fAiiE8DRg MTMI9fq02l7wkIecmDbAhJxk27quCaRDOrvOH7R0pfDEPihR4p/M5dclMkJLnHqOPgWP qRrhCOJDL8kIc50THVJ0ttdcr9tcBgLJAtlXtF+EAnw+m42fo/Fu8qkf1ZfxAcaKOz3Q aJXPadnZgkWAWN9l1uaTmUPhBFEpzHQt9O6eAMRLaHB0gqz95Z9AMveCk3yOSBKSfyYr 32w8Nnl5v0B8z7yYaKD5qxpBTPpkXTyBpgG1vM3jjpQ3scYyckQOLRzRJPu51EB1c/9P 5OQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714934955; x=1715539755; 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=fBm6oxPeCoNnW1L+QveNHU22NEffJtQvwuNSrI9Hc6w=; b=QOQbAq+REqqaNQjHasUrNQYmU3ZPmla0rjvT6mElmOa+BovCE9lrU0aFruE/tE6wrW CUw5vtY0YdtfZlVDz6bHNRa6NxfReciFo6V7gtCLILXUxv8C3i/L+BLnxNhKwiVCTCrh bv0JECOmrR3TC69R6hvLayY7w/gEQNWfwmAHneYWadxl2EWq3309VJqh/Vrs2b12u+ZN HUIARDTe0/W0yYAzVog8IOBWo5rivwTqmNj0uq7RpEhcO6SRw1EGERHYkydHlC2/P3Qi xj8JkJUaHV92skHnNvX20pY3QZaHtaJNurUU8ZDFp4mPPiGZ8oMLrGz+wFRiBhcAqrdq Hv8Q== X-Gm-Message-State: AOJu0YzC18Uo9APPdbPemPWkvTqtykMJwNu0/gZpW9eg4ZQxPxZkfI4i GpM5wopecyfvoltcSAOGLopqnmOwo8w5+y3eqJ++lYtH9PstXn4ZixYo+w== X-Google-Smtp-Source: AGHT+IE9vLrOgTnpxYGkj66X3f1bW2qM5s0pnsYOADHVfPDNlGoJZRePRjUNI+Cxc6JYfDPmgTfe0g== X-Received: by 2002:a05:600c:a01:b0:41b:13a3:6183 with SMTP id z1-20020a05600c0a0100b0041b13a36183mr6679073wmp.24.1714934954602; Sun, 05 May 2024 11:49:14 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e5-20020a05600c4e4500b0041906397ab7sm13482088wmq.3.2024.05.05.11.49.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 May 2024 11:49:13 -0700 (PDT) Message-Id: <75bb5cc0e8a8eac71983a5471d78f913550a21dd.1714934950.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sun, 05 May 2024 18:49:09 +0000 Subject: [PATCH v5 2/3] builtin/commit: refactor --trailer logic 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: Junio C Hamano , Patrick Steinhardt , John Passaro , John Passaro , John Passaro From: John Passaro From: John Passaro git-commit adds user trailers to the commit message by passing its `--trailer` arguments to a child process running `git-interpret-trailers --in-place`. This logic is broadly useful, not just for git-commit but for other commands constructing message bodies (e.g. git-tag). Let's move this logic from git-commit to a new function in the trailer API, so that it can be re-used in other commands. Helped-by: Patrick Steinhardt Helped-by: Junio C Hamano Signed-off-by: John Passaro --- builtin/commit.c | 10 ++-------- trailer.c | 12 ++++++++++++ trailer.h | 9 +++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/builtin/commit.c b/builtin/commit.c index 5a3248370db..63cd090b6f2 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -38,6 +38,7 @@ #include "commit-reach.h" #include "commit-graph.h" #include "pretty.h" +#include "trailer.h" static const char * const builtin_commit_usage[] = { N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u] [--amend]\n" @@ -1030,14 +1031,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, fclose(s->fp); if (trailer_args.nr) { - struct child_process run_trailer = CHILD_PROCESS_INIT; - - strvec_pushl(&run_trailer.args, "interpret-trailers", - "--in-place", "--no-divider", - git_path_commit_editmsg(), NULL); - strvec_pushv(&run_trailer.args, trailer_args.v); - run_trailer.git_cmd = 1; - if (run_command(&run_trailer)) + if (amend_file_with_trailers(git_path_commit_editmsg(), &trailer_args)) die(_("unable to pass trailers to --trailers")); strvec_clear(&trailer_args); } diff --git a/trailer.c b/trailer.c index c72ae687099..724cb78be5f 100644 --- a/trailer.c +++ b/trailer.c @@ -1170,3 +1170,15 @@ void trailer_iterator_release(struct trailer_iterator *iter) strbuf_release(&iter->val); strbuf_release(&iter->key); } + +int amend_file_with_trailers(const char *path, const struct strvec *trailer_args) +{ + struct child_process run_trailer = CHILD_PROCESS_INIT; + + run_trailer.git_cmd = 1; + strvec_pushl(&run_trailer.args, "interpret-trailers", + "--in-place", "--no-divider", + path, NULL); + strvec_pushv(&run_trailer.args, trailer_args->v); + return run_command(&run_trailer); +} diff --git a/trailer.h b/trailer.h index 9f42aa75994..c364405267a 100644 --- a/trailer.h +++ b/trailer.h @@ -4,6 +4,8 @@ #include "list.h" #include "strbuf.h" +struct strvec; + enum trailer_where { WHERE_DEFAULT, WHERE_END, @@ -158,4 +160,11 @@ int trailer_iterator_advance(struct trailer_iterator *iter); */ void trailer_iterator_release(struct trailer_iterator *iter); +/* + * Augment a file to add trailers to it by running git-interpret-trailers. + * This calls run_command() and its return value is the same (i.e. 0 for + * success, various non-zero for other errors). See run-command.h. + */ +int amend_file_with_trailers(const char *path, const struct strvec *trailer_args); + #endif /* TRAILER_H */ From patchwork Sun May 5 18:49:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Passaro X-Patchwork-Id: 13654618 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (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 A4C346D1A8 for ; Sun, 5 May 2024 18:49:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714934959; cv=none; b=TrlKvUVPSjXi/j3uQzkJlRV0/5lfBleNidApqrYN00Qj6F3JOeemBE5AZDYe+ozkLLJn7NGlQsECAmRDiE3zcg3Mtqn/LrY3MtzR0J9TaKRYltTRttNOiwbBtW57ZV6eMJLW4NlcWQ+r79wpIHw4w66hD6fm3piPFHovwUSOowk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714934959; c=relaxed/simple; bh=poaegycawdwBj3FTY1rXxGEDfXi/Olj0qrog+9FfMDs=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=jf5lpjkz0/4wHAmuZ8ifh42opJxoLfLZzj1k4bq7yqMRicfhzGuXfoGpM8B4Lx2Err39u/aZckyQ76vAcotffUIaSrmFvB/FXE5e8i3KXsVbgmRpUh53gGkQr9AEoTTbNqyxyxCeFX/MBKN2SECQ1WhUaXyo8oFokpT7dTcycNc= 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=NpRw2JkH; arc=none smtp.client-ip=209.85.221.54 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="NpRw2JkH" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-34db6a29998so750204f8f.0 for ; Sun, 05 May 2024 11:49:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1714934956; x=1715539756; 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=MH5bEnuYpOYbBHRAm5rTss0FWMHmjxB0ZCuo/ZueRdQ=; b=NpRw2JkH+Y/oQS+XZqSuiLnBuADADWYsj5Nr7G0UgCO/VLamZqdyalmYd4X22CZcRe XxG0j/jViuOGWEqFpghOYLUOwZG5EhPF7Nulsfhd94EjwDRiYDm+t5z8wJDt5XsZvDqT 8jvqezgHzUWXbUjM/LjL/VI53xn6DoEOzADAFhW5qmPs3WDVfzgN2KToL78kAWEZNNHl pBzQ86RkmJZhOPxF0ZTH/0aVQW4T4sHeyFHK2UfX3iFFkCIVpAESCB11U9FECaQwkUnQ 7niA+pIrEXoK1P5pALQzAD/AYAnjR/EEehva/t88hVxZ+g+AoaqYrOb1e99vCFLGmmbG Sz9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714934956; x=1715539756; 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=MH5bEnuYpOYbBHRAm5rTss0FWMHmjxB0ZCuo/ZueRdQ=; b=dHa+NXFVgG8vsQZzcgW25C3rpN6Mlb4CT/BUNayeGRq+YxW9ydvB16IlxYHcaf18Qa McSccbLWLckS725EeZTAnL5lbIqULm8cxJWgnB2BkEnBFb4w5JvYmyyhvgDfTO97eiRV OTyLEzP7hq7A+i2WosB/hAEHad57k0KEptkFj6rSPcUsVmJ4bh0GAdes2LzEER47SJOK XcsYmz7HmC3PnEkPQkAFWRD2FiEbOZNJKY3/+fNGx8QgmcUAHApUv1xoBeohEQitFqpF u0gvCbTq9ozepg7lHFFb5Tf4/fYjSztwJgAGZGp6Yh7nSmJxN4Vn6Sl3mJ31qmnMoMrW mwag== X-Gm-Message-State: AOJu0Yy8OEz7GyMCYHuLxaM/j/iFrtDqevIV+XaP6OunHV5igKwYir0I XxMknwmpWY5Cwz3SL9uApdaHjpAydjMxGNTVqFLSgSkjm5watiYyGAhEFQ== X-Google-Smtp-Source: AGHT+IE6sxQ6HC+Ur4oHroIIGtU5CxzpRNzyQOsiNjjsmDWj0tCs9gRqRzib7MOrOfBd79LB3Hji4Q== X-Received: by 2002:adf:e586:0:b0:34d:a4b4:9f60 with SMTP id l6-20020adfe586000000b0034da4b49f60mr6222745wrm.52.1714934955719; Sun, 05 May 2024 11:49:15 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h3-20020a5d4303000000b0034f145b60ebsm1421475wrq.3.2024.05.05.11.49.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 May 2024 11:49:15 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Sun, 05 May 2024 18:49:10 +0000 Subject: [PATCH v5 3/3] builtin/tag: add --trailer option 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: Junio C Hamano , Patrick Steinhardt , John Passaro , John Passaro , John Passaro From: John Passaro From: John Passaro git-tag supports interpreting trailers from an annotated tag message, using --list --format="%(trailers)". However, the available methods to add a trailer to a tag message (namely -F or --editor) are not as ergonomic. In a previous patch, we moved git-commit's implementation of its --trailer option to the trailer.h API. Let's use that new function to teach git-tag the same --trailer option, emulating as much of git-commit's behavior as much as possible. Helped-by: Patrick Steinhardt Signed-off-by: John Passaro --- Documentation/git-tag.txt | 16 +++++- builtin/tag.c | 38 ++++++++++--- t/t7004-tag.sh | 114 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 11 deletions(-) diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 5fe519c31ec..4494729f5e1 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -10,6 +10,7 @@ SYNOPSIS -------- [verse] 'git tag' [-a | -s | -u ] [-f] [-m | -F ] [-e] + [(--trailer [(=|:)])...] [ | ] 'git tag' -d ... 'git tag' [-n[]] -l [--contains ] [--no-contains ] @@ -31,8 +32,8 @@ creates a 'tag' object, and requires a tag message. Unless `-m ` or `-F ` is given, an editor is started for the user to type in the tag message. -If `-m ` or `-F ` is given and `-a`, `-s`, and `-u ` -are absent, `-a` is implied. +If `-m ` or `-F ` or `--trailer [=]` is given +and `-a`, `-s`, and `-u ` are absent, `-a` is implied. Otherwise, a tag reference that points directly at the given object (i.e., a lightweight tag) is created. @@ -178,6 +179,17 @@ This option is only applicable when listing tags without annotation lines. Implies `-a` if none of `-a`, `-s`, or `-u ` is given. +--trailer [(=|:)]:: + Specify a (, ) pair that should be applied as a + trailer. (e.g. `git tag --trailer "Custom-Key: value"` + will add a "Custom-Key" trailer to the tag message.) + The `trailer.*` configuration variables + (linkgit:git-interpret-trailers[1]) can be used to define if + a duplicated trailer is omitted, where in the run of trailers + each trailer would appear, and other details. + The trailers can be extracted in `git tag --list`, using + `--format="%(trailers)"` placeholder. + -e:: --edit:: The message taken from file with `-F` and command line with diff --git a/builtin/tag.c b/builtin/tag.c index 9a33cb50b45..01b19a5b6c9 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -28,9 +28,11 @@ #include "date.h" #include "write-or-die.h" #include "object-file-convert.h" +#include "trailer.h" static const char * const git_tag_usage[] = { N_("git tag [-a | -s | -u ] [-f] [-m | -F ] [-e]\n" + " [(--trailer [(=|:)])...]\n" " [ | ]"), N_("git tag -d ..."), N_("git tag [-n[]] -l [--contains ] [--no-contains ]\n" @@ -290,10 +292,12 @@ static const char message_advice_nested_tag[] = static void create_tag(const struct object_id *object, const char *object_ref, const char *tag, struct strbuf *buf, struct create_tag_options *opt, - struct object_id *prev, struct object_id *result, char *path) + struct object_id *prev, struct object_id *result, + struct strvec *trailer_args, char *path) { enum object_type type; struct strbuf header = STRBUF_INIT; + int should_edit; type = oid_object_info(the_repository, object, NULL); if (type <= OBJ_NONE) @@ -313,13 +317,15 @@ static void create_tag(const struct object_id *object, const char *object_ref, tag, git_committer_info(IDENT_STRICT)); - if (!opt->message_given || opt->use_editor) { + should_edit = opt->use_editor || !opt->message_given; + if (should_edit || trailer_args->nr) { int fd; /* write the template message before editing: */ fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); - if (opt->message_given) { + if (opt->message_given && buf->len) { + strbuf_complete(buf, '\n'); write_or_die(fd, buf->buf, buf->len); strbuf_reset(buf); } else if (!is_null_oid(prev)) { @@ -338,10 +344,19 @@ static void create_tag(const struct object_id *object, const char *object_ref, } close(fd); - if (launch_editor(path, buf, NULL)) { - fprintf(stderr, - _("Please supply the message using either -m or -F option.\n")); - exit(1); + if (trailer_args->nr && amend_file_with_trailers(path, trailer_args)) + die(_("unable to pass trailers to --trailers")); + + if (should_edit) { + if (launch_editor(path, buf, NULL)) { + fprintf(stderr, + _("Please supply the message using either -m or -F option.\n")); + exit(1); + } + } else if (trailer_args->nr) { + strbuf_reset(buf); + if (strbuf_read_file(buf, path, 0) < 0) + die_errno(_("failed to read '%s'"), path); } } @@ -463,6 +478,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; struct ref_format format = REF_FORMAT_INIT; + struct strvec trailer_args = STRVEC_INIT; int icase = 0; int edit_flag = 0; struct option options[] = { @@ -479,6 +495,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) OPT_CALLBACK_F('m', "message", &msg, N_("message"), N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg), OPT_FILENAME('F', "file", &msgfile, N_("read message from file")), + OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"), + N_("add custom trailer(s)"), PARSE_OPT_NONEG), OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")), OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")), OPT_CLEANUP(&cleanup_arg), @@ -548,7 +566,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) opt.sign = 1; set_signing_key(keyid); } - create_tag_object = (opt.sign || annotate || msg.given || msgfile); + create_tag_object = (opt.sign || annotate || msg.given || msgfile || + edit_flag || trailer_args.nr); if ((create_tag_object || force) && (cmdmode != 0)) usage_with_options(git_tag_usage, options); @@ -654,7 +673,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) opt.sign = 1; path = git_pathdup("TAG_EDITMSG"); create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, - path); + &trailer_args, path); } transaction = ref_transaction_begin(&err); @@ -686,6 +705,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) strbuf_release(&reflog_msg); strbuf_release(&msg.buf); strbuf_release(&err); + strvec_clear(&trailer_args); free(msgfile); return ret; } diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 696866d7794..fa6336edf98 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -668,6 +668,115 @@ test_expect_success \ test_cmp expect actual ' +# trailers + +test_expect_success 'create tag with -m and --trailer' ' + get_tag_header tag-with-inline-message-and-trailers $commit commit $time >expect && + cat >>expect <<-\EOF && + create tag with trailers + + my-trailer: here + alt-trailer: there + EOF + git tag -m "create tag with trailers" \ + --trailer my-trailer=here \ + --trailer alt-trailer=there \ + tag-with-inline-message-and-trailers && + get_tag_msg tag-with-inline-message-and-trailers >actual && + test_cmp expect actual +' + +test_expect_success 'list tag extracting trailers' ' + cat >expect <<-\EOF && + my-trailer: here + alt-trailer: there + + EOF + git tag --list --format="%(trailers)" tag-with-inline-message-and-trailers >actual && + test_cmp expect actual +' + +test_expect_success 'create tag with -F and --trailer' ' + echo "create tag from message file using --trailer" >messagefilewithnotrailers && + get_tag_header tag-with-file-message-and-trailers $commit commit $time >expect && + cat >>expect <<-\EOF && + create tag from message file using --trailer + + my-trailer: here + alt-trailer: there + EOF + git tag -F messagefilewithnotrailers \ + --trailer my-trailer=here \ + --trailer alt-trailer=there \ + tag-with-file-message-and-trailers && + get_tag_msg tag-with-file-message-and-trailers >actual && + test_cmp expect actual +' + +test_expect_success 'create tag with -m and --trailer and --edit' ' + write_script fakeeditor <<-\EOF && + sed -e "1s/^/EDITED: /g" <"$1" >"$1-" + mv "$1-" "$1" + EOF + get_tag_header tag-with-edited-inline-message-and-trailers $commit commit $time >expect && + cat >>expect <<-\EOF && + EDITED: create tag with trailers + + my-trailer: here + alt-trailer: there + EOF + GIT_EDITOR=./fakeeditor git tag --edit \ + -m "create tag with trailers" \ + --trailer my-trailer=here \ + --trailer alt-trailer=there \ + tag-with-edited-inline-message-and-trailers && + get_tag_msg tag-with-edited-inline-message-and-trailers >actual && + test_cmp expect actual +' + +test_expect_success 'create tag with -F and --trailer and --edit' ' + echo "create tag from message file using --trailer" >messagefilewithnotrailers && + get_tag_header tag-with-edited-file-message-and-trailers $commit commit $time >expect && + cat >>expect <<-\EOF && + EDITED: create tag from message file using --trailer + + my-trailer: here + alt-trailer: there + EOF + GIT_EDITOR=./fakeeditor git tag --edit \ + -F messagefilewithnotrailers \ + --trailer my-trailer=here \ + --trailer alt-trailer=there \ + tag-with-edited-file-message-and-trailers && + get_tag_msg tag-with-edited-file-message-and-trailers >actual && + test_cmp expect actual +' + +test_expect_success 'create annotated tag and force editor when only --trailer is given' ' + write_script fakeeditor <<-\EOF && + echo "add a line" >"$1-" + cat <"$1" >>"$1-" + mv "$1-" "$1" + EOF + get_tag_header tag-with-trailers-and-no-message $commit commit $time >expect && + cat >>expect <<-\EOF && + add a line + + my-trailer: here + alt-trailer: there + EOF + GIT_EDITOR=./fakeeditor git tag \ + --trailer my-trailer=here \ + --trailer alt-trailer=there \ + tag-with-trailers-and-no-message && + get_tag_msg tag-with-trailers-and-no-message >actual && + test_cmp expect actual +' + +test_expect_success 'bad editor causes panic when only --trailer is given' ' + test_must_fail env GIT_EDITOR=false git tag --trailer my-trailer=here tag-will-not-exist +' + # listing messages for annotated non-signed tags: test_expect_success \ @@ -810,6 +919,11 @@ test_expect_success 'git tag --format with ahead-behind' ' refs/tags/tag-lines 0 1 ! refs/tags/tag-one-line 0 1 ! refs/tags/tag-right 0 0 ! + refs/tags/tag-with-edited-file-message-and-trailers 0 1 ! + refs/tags/tag-with-edited-inline-message-and-trailers 0 1 ! + refs/tags/tag-with-file-message-and-trailers 0 1 ! + refs/tags/tag-with-inline-message-and-trailers 0 1 ! + refs/tags/tag-with-trailers-and-no-message 0 1 ! refs/tags/tag-zero-lines 0 1 ! EOF git tag -l --format="%(refname) %(ahead-behind:HEAD) !" >actual 2>err &&