From patchwork Thu Aug 10 16:36:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349729 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 149DFC04A6A for ; Thu, 10 Aug 2023 16:37:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234595AbjHJQho (ORCPT ); Thu, 10 Aug 2023 12:37:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232475AbjHJQh0 (ORCPT ); Thu, 10 Aug 2023 12:37:26 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5A2A3594 for ; Thu, 10 Aug 2023 09:37:13 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id 98e67ed59e1d1-268113acd37so2583577a91.0 for ; Thu, 10 Aug 2023 09:37:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685432; x=1692290232; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=gvUy7Y4qaaLH7U9v1tJENsPpGvTJY0Uq1ZdI0IMvB/o=; b=pXosnucNH3DYRiGcPeH4fTStf5lavWjqx+g8HborWJvomw0+azcgsOoVxDOquiDunT sANjha8/jeDlTvGThswcz/l+tBkOJh/RXCGFn9fHZ/GPsJCfs01xOZG2iSFa8t9VGNgn NJIXgbPfIIaFOwy1sOqWfTfFk2DZ4WZ9YIfrdb+7O4sUktOiAPXmsO11C36D8H9e+nJW w2d0WSAALfwWMSzGFZUi2dnDns0hcPkP/PrLU0Fcu0lz+gDKBiwg2pOOYfTE19rIGXTd vd+vSODk30Tu6rowrKKXvRD2/BQJmX6sBtVz/ZMsDf0Fo4DgHAr675OpOA5tqELenao2 clrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685432; x=1692290232; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=gvUy7Y4qaaLH7U9v1tJENsPpGvTJY0Uq1ZdI0IMvB/o=; b=VBRLnv0MbVRDGP08pdtmVMwHOw7pRLKBq6b1CylK+qJDO+/+PLuV3KUqdQBdx+L1/z A4PwsT6UUeUi9VaQ4DhuaoD3iVuyFN5Xjo3L+u3EQhf9Hi8+Fp0jmaWF7DMiyK1DckRo LyxE7wcc9hOSnKzn1Q/R7NgOqSHx6ACAkGGxBhJK8xzn/YSExEbB1+OsrSIMtVmP7POv L8SR73OvQFRyr4siBGdg9cCRlFCS8r6CAeCETiGi5FuQ//mve+bhdKLAqZneCdRjGatj hvoTuavc7H9bDVELnwz7AuezKPSBNvVicFUG8bjFgbHRITiZ9a09nxXcNZNtCJTKgPB8 ttEg== X-Gm-Message-State: AOJu0YyfA7bvs2VaYuU7Mdli5Sxe6lFD4cgf6b05t1t5KQoq4IQElU52 EQrlwB/jRhlcfHiugmp4NtxASN+6mxfYgngBL+EUbR9Xft9ZQ3K/1hfnVvcVvTle/owOSD/6GpW /xXhT6863hOHCBZ2iK+eEx7teCbToqjgc1P3/2v36A+6m+v1rpUx5PZNudD8or/KwlA== X-Google-Smtp-Source: AGHT+IGk9Lc0AmXQsmJJt4ZBuyWk56nlGqROMlEj9y+ZfMiVDdw0P/Hv9LVRNz4c/3sbgmmjyCqfxHV/yC67b4U= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a17:90b:1197:b0:269:32cb:3321 with SMTP id gk23-20020a17090b119700b0026932cb3321mr591843pjb.0.1691685432246; Thu, 10 Aug 2023 09:37:12 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:48 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-1-calvinwan@google.com> Subject: [RFC PATCH v2 1/7] hex-ll: split out functionality from hex From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Separate out hex functionality that doesn't require a hash algo into hex-ll.[ch]. Since the hash algo is currently a global that sits in repository, this separation removes that dependency for files that only need basic hex manipulation functions. Signed-off-by: Calvin Wan --- Makefile | 1 + color.c | 2 +- hex-ll.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ hex-ll.h | 27 +++++++++++++++++++++++++++ hex.c | 47 ----------------------------------------------- hex.h | 24 +----------------------- mailinfo.c | 2 +- strbuf.c | 2 +- url.c | 2 +- urlmatch.c | 2 +- 10 files changed, 83 insertions(+), 75 deletions(-) create mode 100644 hex-ll.c create mode 100644 hex-ll.h diff --git a/Makefile b/Makefile index 045e2187c4..83b385b0be 100644 --- a/Makefile +++ b/Makefile @@ -1040,6 +1040,7 @@ LIB_OBJS += hash-lookup.o LIB_OBJS += hashmap.o LIB_OBJS += help.o LIB_OBJS += hex.o +LIB_OBJS += hex-ll.o LIB_OBJS += hook.o LIB_OBJS += ident.o LIB_OBJS += json-writer.o diff --git a/color.c b/color.c index 83abb11eda..f3c0a4659b 100644 --- a/color.c +++ b/color.c @@ -3,7 +3,7 @@ #include "color.h" #include "editor.h" #include "gettext.h" -#include "hex.h" +#include "hex-ll.h" #include "pager.h" #include "strbuf.h" diff --git a/hex-ll.c b/hex-ll.c new file mode 100644 index 0000000000..4d7ece1de5 --- /dev/null +++ b/hex-ll.c @@ -0,0 +1,49 @@ +#include "git-compat-util.h" +#include "hex-ll.h" + +const signed char hexval_table[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */ + 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */ + 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */ + -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */ + -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */ + -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */ + -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */ + -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */ + -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */ + -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */ +}; + +int hex_to_bytes(unsigned char *binary, const char *hex, size_t len) +{ + for (; len; len--, hex += 2) { + unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]); + + if (val & ~0xff) + return -1; + *binary++ = val; + } + return 0; +} diff --git a/hex-ll.h b/hex-ll.h new file mode 100644 index 0000000000..a381fa8556 --- /dev/null +++ b/hex-ll.h @@ -0,0 +1,27 @@ +#ifndef HEX_LL_H +#define HEX_LL_H + +extern const signed char hexval_table[256]; +static inline unsigned int hexval(unsigned char c) +{ + return hexval_table[c]; +} + +/* + * Convert two consecutive hexadecimal digits into a char. Return a + * negative value on error. Don't run over the end of short strings. + */ +static inline int hex2chr(const char *s) +{ + unsigned int val = hexval(s[0]); + return (val & ~0xf) ? val : (val << 4) | hexval(s[1]); +} + +/* + * Read `len` pairs of hexadecimal digits from `hex` and write the + * values to `binary` as `len` bytes. Return 0 on success, or -1 if + * the input does not consist of hex digits). + */ +int hex_to_bytes(unsigned char *binary, const char *hex, size_t len); + +#endif diff --git a/hex.c b/hex.c index 7bb440e794..03e55841ed 100644 --- a/hex.c +++ b/hex.c @@ -2,53 +2,6 @@ #include "hash.h" #include "hex.h" -const signed char hexval_table[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */ - 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */ - 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */ - -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */ - -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */ - -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */ - -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */ - -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */ - -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */ - -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */ -}; - -int hex_to_bytes(unsigned char *binary, const char *hex, size_t len) -{ - for (; len; len--, hex += 2) { - unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]); - - if (val & ~0xff) - return -1; - *binary++ = val; - } - return 0; -} - static int get_hash_hex_algop(const char *hex, unsigned char *hash, const struct git_hash_algo *algop) { diff --git a/hex.h b/hex.h index 7df4b3c460..c07c8b34c2 100644 --- a/hex.h +++ b/hex.h @@ -2,22 +2,7 @@ #define HEX_H #include "hash-ll.h" - -extern const signed char hexval_table[256]; -static inline unsigned int hexval(unsigned char c) -{ - return hexval_table[c]; -} - -/* - * Convert two consecutive hexadecimal digits into a char. Return a - * negative value on error. Don't run over the end of short strings. - */ -static inline int hex2chr(const char *s) -{ - unsigned int val = hexval(s[0]); - return (val & ~0xf) ? val : (val << 4) | hexval(s[1]); -} +#include "hex-ll.h" /* * Try to read a SHA1 in hexadecimal format from the 40 characters @@ -32,13 +17,6 @@ int get_oid_hex(const char *hex, struct object_id *sha1); /* Like get_oid_hex, but for an arbitrary hash algorithm. */ int get_oid_hex_algop(const char *hex, struct object_id *oid, const struct git_hash_algo *algop); -/* - * Read `len` pairs of hexadecimal digits from `hex` and write the - * values to `binary` as `len` bytes. Return 0 on success, or -1 if - * the input does not consist of hex digits). - */ -int hex_to_bytes(unsigned char *binary, const char *hex, size_t len); - /* * Convert a binary hash in "unsigned char []" or an object name in * "struct object_id *" to its hex equivalent. The `_r` variant is reentrant, diff --git a/mailinfo.c b/mailinfo.c index 2aeb20e5e6..eb34c30be7 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "config.h" #include "gettext.h" -#include "hex.h" +#include "hex-ll.h" #include "utf8.h" #include "strbuf.h" #include "mailinfo.h" diff --git a/strbuf.c b/strbuf.c index 8dac52b919..a2a05fe168 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1,6 +1,6 @@ #include "git-compat-util.h" #include "gettext.h" -#include "hex.h" +#include "hex-ll.h" #include "strbuf.h" #include "string-list.h" #include "utf8.h" diff --git a/url.c b/url.c index 2e1a9f6fee..282b12495a 100644 --- a/url.c +++ b/url.c @@ -1,5 +1,5 @@ #include "git-compat-util.h" -#include "hex.h" +#include "hex-ll.h" #include "strbuf.h" #include "url.h" diff --git a/urlmatch.c b/urlmatch.c index eba0bdd77f..f1aa87d1dd 100644 --- a/urlmatch.c +++ b/urlmatch.c @@ -1,6 +1,6 @@ #include "git-compat-util.h" #include "gettext.h" -#include "hex.h" +#include "hex-ll.h" #include "strbuf.h" #include "urlmatch.h" From patchwork Thu Aug 10 16:36:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349728 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A9419C001E0 for ; Thu, 10 Aug 2023 16:37:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236432AbjHJQhm (ORCPT ); Thu, 10 Aug 2023 12:37:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235627AbjHJQh1 (ORCPT ); Thu, 10 Aug 2023 12:37:27 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF868359C for ; Thu, 10 Aug 2023 09:37:14 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-583a89cccf6so14877237b3.1 for ; Thu, 10 Aug 2023 09:37:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685434; x=1692290234; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=kVc93oMajibcMyHFtL7WCAKEoCpgyDySoMcdNNdScTg=; b=wAM5xWwQw2c/Mkc9UEWTmj9fcWiFREam/HL6rwFbT11AMbAYKKGmG5NKeRs4yaVHSr 8IUfDdeyfq+OrtTH+TmlCNnMSelPi3g4a9r05yBtxxyKpDCwNzzCJQWNcT8UvNScsjkM OPYkOdZuWCA7Z+QNO2PHq5Lp9DV5WGTVuVPa06D1aru2oUkXpDuGtMOhcIoco+fUEmzk dtamE+mrwSjsph5BqUmkpPisK8ldXe7gcnIT3Svyf8SuMj9PiZh0ixi/vG+IAzo65N8X ZX+yxIGbSqB/bClrKA84ntIHhneBSSU3RySM/dfItd4aSrhABmhYLY5aGKJ3H20d5xSg 2DnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685434; x=1692290234; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=kVc93oMajibcMyHFtL7WCAKEoCpgyDySoMcdNNdScTg=; b=HdV58bbVv3bX6zRN7jyef/GWVzbgtQf8mB9FeQw4pV8eufVnrdNz3hc9LLKAMWpiw8 0Vw3Lu7toPsbFKiqKPL5GmN3RzB/tdqidB3XQilySIRznT+h+ZVQHGRM7BC3uXFB03Xe Q67fdYfspws5owzgkJNEsZzxUmc6fIUJ2zxQOHFFvAnwftGjLln/P5msZG7c4N6xl1Du WPb9Ha2SV9swuZ9qcViPtf+a9VHmUjrmgA0ktkcxW8X0Kd5wNtV0LGRU+mgUBH50tYKF sy59VUMARtUsbvOs8QlljYDbH8n5AqpUAi6AnHKwNkb89+sZV8BUJiD6Wbc2ChCo9tOu G0qw== X-Gm-Message-State: AOJu0YyKPNWHo1P66oTGqn5YS66t0wmmqjiqvZHp/63ANddbnLOFwS2l afxsWyGLzzGZKEozpv7H5zDnwHQJStq/Ms70lzQkB8hCmyxX2ZM3VEIvGrU2jJ1CNE14DQW11DF 2U/s3CQ6q8jYgQWlfM4A2E/DZNiIdC7L4exEfBG0FsmwV+ydJnUqjImja/KCIYSfG6g== X-Google-Smtp-Source: AGHT+IF5pDJRN1we7a2RoiMM5MP1l399heEnPta2DbVgxTC0S8wLHL19tb5R17fWEN8TlmQ3KPKOHiANn2FNqGI= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a5b:c12:0:b0:d62:7f3f:621d with SMTP id f18-20020a5b0c12000000b00d627f3f621dmr49368ybq.11.1691685433791; Thu, 10 Aug 2023 09:37:13 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:49 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-2-calvinwan@google.com> Subject: [RFC PATCH v2 2/7] object: move function to object.c From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org While remove_or_warn() is a simple ternary operator to call two other wrapper functions, it creates an unnecessary dependency to object.h in wrapper.c. Therefore move the function to object.[ch] where the concept of GITLINKs is first defined. Signed-off-by: Calvin Wan --- object.c | 5 +++++ object.h | 6 ++++++ wrapper.c | 6 ------ wrapper.h | 5 ----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/object.c b/object.c index 60f954194f..cb29fcc304 100644 --- a/object.c +++ b/object.c @@ -617,3 +617,8 @@ void parsed_object_pool_clear(struct parsed_object_pool *o) FREE_AND_NULL(o->object_state); FREE_AND_NULL(o->shallow_stat); } + +int remove_or_warn(unsigned int mode, const char *file) +{ + return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file); +} diff --git a/object.h b/object.h index 5871615fee..e908ef6515 100644 --- a/object.h +++ b/object.h @@ -284,4 +284,10 @@ void clear_object_flags(unsigned flags); */ void repo_clear_commit_marks(struct repository *r, unsigned int flags); +/* + * Calls the correct function out of {unlink,rmdir}_or_warn based on + * the supplied file mode. + */ +int remove_or_warn(unsigned int mode, const char *path); + #endif /* OBJECT_H */ diff --git a/wrapper.c b/wrapper.c index 22be9812a7..118d3033de 100644 --- a/wrapper.c +++ b/wrapper.c @@ -5,7 +5,6 @@ #include "abspath.h" #include "config.h" #include "gettext.h" -#include "object.h" #include "repository.h" #include "strbuf.h" #include "trace2.h" @@ -647,11 +646,6 @@ int rmdir_or_warn(const char *file) return warn_if_unremovable("rmdir", file, rmdir(file)); } -int remove_or_warn(unsigned int mode, const char *file) -{ - return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file); -} - static int access_error_is_ok(int err, unsigned flag) { return (is_missing_file_error(err) || diff --git a/wrapper.h b/wrapper.h index c85b1328d1..272795f863 100644 --- a/wrapper.h +++ b/wrapper.h @@ -111,11 +111,6 @@ int unlink_or_msg(const char *file, struct strbuf *err); * not exist. */ int rmdir_or_warn(const char *path); -/* - * Calls the correct function out of {unlink,rmdir}_or_warn based on - * the supplied file mode. - */ -int remove_or_warn(unsigned int mode, const char *path); /* * Call access(2), but warn for any error except "missing file" From patchwork Thu Aug 10 16:36:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349730 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6C04EC001E0 for ; Thu, 10 Aug 2023 16:38:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235603AbjHJQhq (ORCPT ); Thu, 10 Aug 2023 12:37:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234110AbjHJQh2 (ORCPT ); Thu, 10 Aug 2023 12:37:28 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BDB6235A5 for ; Thu, 10 Aug 2023 09:37:15 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-5646e695ec1so1660027a12.1 for ; Thu, 10 Aug 2023 09:37:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685435; x=1692290235; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hxwe3WOPjWpLytPYCre2jdZg6NAXnh3CgUy2eTaECm0=; b=V9faoNYq2YG2yoGVogZwr1ISMPT0fUs0yb2kJ50xxKWRvH4t/xEo+cSnd0Lv+aH0ef qR8VJTc8huFopMmiFYdRI2OWjhvHBHHkUsXXnuL4NUk+HdMoUpfCVhkm7pKUOnW6gJY2 N3loc5NkDzDU71laY4J3koe5XxQ3baNyGT6edIZ52PQhSzKFc0pB8Bd5YK6Wl+xZIqA3 gITnDYfUQtcp4LneRv0HA0ed1r1Ok4gvP9EaU5fXTmmTNWPUR4dhj/zYxtqAzFAgfuor 6MaEti+t08xvl/Zs7HCcIlDTJST5ItilXTeSJR2prhf46lzzagh/1mP54v2jPSvN+pyp 6yQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685435; x=1692290235; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hxwe3WOPjWpLytPYCre2jdZg6NAXnh3CgUy2eTaECm0=; b=P1W3cBBovGAfx36VvMv9zfdt6q+ixtr3Akbso3AK6K4z69PCTOJes0vLkG9QLwzWo9 RMsEsUpuf8GurLZH3RMT5qJHpIPL/5YUKijJ0kIi/XulNRty8ojoUnNYHz72FFy/d+SH 6OKl/FSSHzQfT8Osbf+oxKfRr12i+QKenIIMbiLQxrPO1C0EvDFWvA6XGydyU45T7fN5 Zz5ZpPO5IzKCpDluw1wGtW5FHKs1n+l0VcH/jw1eM1I9gCs/7dBd/SiF4gCWbDs7Slyv 3clUrBw6J7ba7NhjAq4Btux8vTsVrSWqQCFOD5HYSvL2BsE1yfrasTSDlArxmBpn92l4 wadw== X-Gm-Message-State: AOJu0YwToe3UkYRmKxxiRniFiLOZ2jtaXCYJmMWYOYkZFIUWe6JTIjqF 4ITv+cFOtmDEsZfatyCMwTW+HRsErSrzHNycmZKqL+4ZB8ZI5Koqd3gPz4OG//XcKxQ+X2BFxH4 RpRLgi1gB4/8e68aTATu9ntOH1CNhpIPkWeQbc0aA6zGSI/RhocnehH8Dl5lwR5ebkw== X-Google-Smtp-Source: AGHT+IFLVbIbZdSFKMo0thT1gdW5WpS0+5bEAD1/VccPY0yHzxxhsVddK5feN/jsgzzTbGHGTaEU2R28jb6I9Dg= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a17:902:f543:b0:1bb:a367:a8b with SMTP id h3-20020a170902f54300b001bba3670a8bmr997503plf.4.1691685435220; Thu, 10 Aug 2023 09:37:15 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:50 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-3-calvinwan@google.com> Subject: [RFC PATCH v2 3/7] config: correct bad boolean env value error message From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org An incorrectly defined boolean environment value would result in the following error message: bad boolean config value '%s' for '%s' This is a misnomer since environment value != config value. Instead of calling git_config_bool() to parse the environment value, mimic the functionality inside of git_config_bool() but with the correct error message. Signed-off-by: Calvin Wan --- config.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/config.c b/config.c index 09851a6909..5b71ef1624 100644 --- a/config.c +++ b/config.c @@ -2172,7 +2172,14 @@ void git_global_config(char **user_out, char **xdg_out) int git_env_bool(const char *k, int def) { const char *v = getenv(k); - return v ? git_config_bool(k, v) : def; + int val; + if (!v) + return def; + val = git_parse_maybe_bool(v); + if (val < 0) + die(_("bad boolean environment value '%s' for '%s'"), + v, k); + return val; } /* From patchwork Thu Aug 10 16:36:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349732 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41E1FC001E0 for ; Thu, 10 Aug 2023 16:38:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235235AbjHJQiP (ORCPT ); Thu, 10 Aug 2023 12:38:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235910AbjHJQha (ORCPT ); Thu, 10 Aug 2023 12:37:30 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E2942D64 for ; Thu, 10 Aug 2023 09:37:18 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-583c1903ad3so15061967b3.2 for ; Thu, 10 Aug 2023 09:37:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685437; x=1692290237; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5pmbmykk0VUEcMBxo5+B/tMz+QX+7Dgb3Sd2ULDwis8=; b=PKDjeED0yLWHs5xCdV8l8nIZCQiqWgyx+gQ8NRUOSFkUWfRRjpm2tuvvPEf3oboBxW yb1ZE7WwxZ56gdgiA0jGEwzT+aPnOiCt0RLk33+F/Vz+lOAeUqVuf7iHtNPdnUD6wWu/ SYu09anl3eWs4iKXyPxlQWgX3zySB/hQhZMFCMKd6lPKgvmS79uTPFSyZCiusEmCl70o a+Cujp4tZLYWrjeD1QxyJwkPx41BRofsICAmu+zO5F+MMfN0oShFpsuftYtPPgj1lBaZ DF9AdNIaPKo2zDBfL5M5AP/pgYQx37HHjBhyS1u6Z4LTV1HWgRJutKzL5BdnCMypPHqi h/wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685437; x=1692290237; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5pmbmykk0VUEcMBxo5+B/tMz+QX+7Dgb3Sd2ULDwis8=; b=N1/d1u14zg02o4cbiiqCqEdbN5Ejm5E9w631IBiPFfZFUbqHTH7NioBbtr8KHrQMQd /Je/+2IJLQLEpbOrZwOhmwGc/DoVQQkAnemrtM/Ym6zqWoR4AI08j9jY0E8H0ujEf+gH 8S0iqAkHjk9ymS3z1GSBOMZ4YIOxmGFV9TQeDifbEzyZ6buump7S9fnirK4DimWSkbgn mpuqlvLu9ihC+vN9gK2AwipWBPk4XY2GDjNaS1CVqM47Y+J7dKkr+lt8xb0PPO4zz5+g fr6hoQzoL+hl+Kr7TJH7MHBautG/uYl/WpO48tjs8fY+QLwOUMVY4zV9RTrVcIi6D4g4 b1tA== X-Gm-Message-State: AOJu0YwzN7Vvet9z50rS2gX4M45ABLyMkXCWb2cXqyY+izPk3YafNrOO K/uAP2vLe6SC3lQPwARTyrpFHVY+NQBWZ2zpHk6gelwaDT1CgTnRur5GtZG8XLku8YS25ZqMoDz TcowcgS6fDlG214M0YwAPq3QTMmJyqZfinP+GIB2PF61s1AuBxfJ/C3rNQSjKAA/FMw== X-Google-Smtp-Source: AGHT+IGCMj180C04aHoArV/JuxvSXKkwEpPlQtbau1HVv2vLUu6yNC44JxWkc6YIOKtCz/X1n+ju0lcWqxm4sYk= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a81:ad64:0:b0:583:4f82:b9d9 with SMTP id l36-20020a81ad64000000b005834f82b9d9mr56092ywk.5.1691685437224; Thu, 10 Aug 2023 09:37:17 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:51 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-4-calvinwan@google.com> Subject: [RFC PATCH v2 4/7] parse: create new library for parsing strings and env values From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org While string and environment value parsing is mainly consumed by config.c, there are other files that only need parsing functionality and not config functionality. By separating out string and environment value parsing from config, those files can instead be dependent on parse, which has a much smaller dependency chain than config. Move general string and env parsing functions from config.[ch] to parse.[ch]. Signed-off-by: Calvin Wan --- Makefile | 1 + attr.c | 2 +- config.c | 180 +----------------------------------- config.h | 14 +-- pack-objects.c | 2 +- pack-revindex.c | 2 +- parse-options.c | 3 +- parse.c | 182 +++++++++++++++++++++++++++++++++++++ parse.h | 20 ++++ pathspec.c | 2 +- preload-index.c | 2 +- progress.c | 2 +- prompt.c | 2 +- rebase.c | 2 +- t/helper/test-env-helper.c | 2 +- unpack-trees.c | 2 +- wrapper.c | 2 +- write-or-die.c | 2 +- 18 files changed, 219 insertions(+), 205 deletions(-) create mode 100644 parse.c create mode 100644 parse.h diff --git a/Makefile b/Makefile index 83b385b0be..e9ad9f9ef1 100644 --- a/Makefile +++ b/Makefile @@ -1091,6 +1091,7 @@ LIB_OBJS += pack-write.o LIB_OBJS += packfile.o LIB_OBJS += pager.o LIB_OBJS += parallel-checkout.o +LIB_OBJS += parse.o LIB_OBJS += parse-options-cb.o LIB_OBJS += parse-options.o LIB_OBJS += patch-delta.o diff --git a/attr.c b/attr.c index e9c81b6e07..cb047b4618 100644 --- a/attr.c +++ b/attr.c @@ -7,7 +7,7 @@ */ #include "git-compat-util.h" -#include "config.h" +#include "parse.h" #include "environment.h" #include "exec-cmd.h" #include "attr.h" diff --git a/config.c b/config.c index 5b71ef1624..cdd70999aa 100644 --- a/config.c +++ b/config.c @@ -11,6 +11,7 @@ #include "date.h" #include "branch.h" #include "config.h" +#include "parse.h" #include "convert.h" #include "environment.h" #include "gettext.h" @@ -1204,129 +1205,6 @@ static int git_parse_source(struct config_source *cs, config_fn_t fn, return error_return; } -static uintmax_t get_unit_factor(const char *end) -{ - if (!*end) - return 1; - else if (!strcasecmp(end, "k")) - return 1024; - else if (!strcasecmp(end, "m")) - return 1024 * 1024; - else if (!strcasecmp(end, "g")) - return 1024 * 1024 * 1024; - return 0; -} - -static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max) -{ - if (value && *value) { - char *end; - intmax_t val; - intmax_t factor; - - if (max < 0) - BUG("max must be a positive integer"); - - errno = 0; - val = strtoimax(value, &end, 0); - if (errno == ERANGE) - return 0; - if (end == value) { - errno = EINVAL; - return 0; - } - factor = get_unit_factor(end); - if (!factor) { - errno = EINVAL; - return 0; - } - if ((val < 0 && -max / factor > val) || - (val > 0 && max / factor < val)) { - errno = ERANGE; - return 0; - } - val *= factor; - *ret = val; - return 1; - } - errno = EINVAL; - return 0; -} - -static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max) -{ - if (value && *value) { - char *end; - uintmax_t val; - uintmax_t factor; - - /* negative values would be accepted by strtoumax */ - if (strchr(value, '-')) { - errno = EINVAL; - return 0; - } - errno = 0; - val = strtoumax(value, &end, 0); - if (errno == ERANGE) - return 0; - if (end == value) { - errno = EINVAL; - return 0; - } - factor = get_unit_factor(end); - if (!factor) { - errno = EINVAL; - return 0; - } - if (unsigned_mult_overflows(factor, val) || - factor * val > max) { - errno = ERANGE; - return 0; - } - val *= factor; - *ret = val; - return 1; - } - errno = EINVAL; - return 0; -} - -int git_parse_int(const char *value, int *ret) -{ - intmax_t tmp; - if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int))) - return 0; - *ret = tmp; - return 1; -} - -static int git_parse_int64(const char *value, int64_t *ret) -{ - intmax_t tmp; - if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t))) - return 0; - *ret = tmp; - return 1; -} - -int git_parse_ulong(const char *value, unsigned long *ret) -{ - uintmax_t tmp; - if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long))) - return 0; - *ret = tmp; - return 1; -} - -int git_parse_ssize_t(const char *value, ssize_t *ret) -{ - intmax_t tmp; - if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(ssize_t))) - return 0; - *ret = tmp; - return 1; -} - static int reader_config_name(struct config_reader *reader, const char **out); static int reader_origin_type(struct config_reader *reader, enum config_origin_type *type); @@ -1404,23 +1282,6 @@ ssize_t git_config_ssize_t(const char *name, const char *value) return ret; } -static int git_parse_maybe_bool_text(const char *value) -{ - if (!value) - return 1; - if (!*value) - return 0; - if (!strcasecmp(value, "true") - || !strcasecmp(value, "yes") - || !strcasecmp(value, "on")) - return 1; - if (!strcasecmp(value, "false") - || !strcasecmp(value, "no") - || !strcasecmp(value, "off")) - return 0; - return -1; -} - static const struct fsync_component_name { const char *name; enum fsync_component component_bits; @@ -1495,16 +1356,6 @@ static enum fsync_component parse_fsync_components(const char *var, const char * return (current & ~negative) | positive; } -int git_parse_maybe_bool(const char *value) -{ - int v = git_parse_maybe_bool_text(value); - if (0 <= v) - return v; - if (git_parse_int(value, &v)) - return !!v; - return -1; -} - int git_config_bool_or_int(const char *name, const char *value, int *is_bool) { int v = git_parse_maybe_bool_text(value); @@ -2165,35 +2016,6 @@ void git_global_config(char **user_out, char **xdg_out) *xdg_out = xdg_config; } -/* - * Parse environment variable 'k' as a boolean (in various - * possible spellings); if missing, use the default value 'def'. - */ -int git_env_bool(const char *k, int def) -{ - const char *v = getenv(k); - int val; - if (!v) - return def; - val = git_parse_maybe_bool(v); - if (val < 0) - die(_("bad boolean environment value '%s' for '%s'"), - v, k); - return val; -} - -/* - * Parse environment variable 'k' as ulong with possibly a unit - * suffix; if missing, use the default value 'val'. - */ -unsigned long git_env_ulong(const char *k, unsigned long val) -{ - const char *v = getenv(k); - if (v && !git_parse_ulong(v, &val)) - die(_("failed to parse %s"), k); - return val; -} - int git_config_system(void) { return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0); diff --git a/config.h b/config.h index 247b572b37..7a7f53e503 100644 --- a/config.h +++ b/config.h @@ -3,7 +3,7 @@ #include "hashmap.h" #include "string-list.h" - +#include "parse.h" /** * The config API gives callers a way to access Git configuration files @@ -205,16 +205,6 @@ int config_with_options(config_fn_t fn, void *, * The following helper functions aid in parsing string values */ -int git_parse_ssize_t(const char *, ssize_t *); -int git_parse_ulong(const char *, unsigned long *); -int git_parse_int(const char *value, int *ret); - -/** - * Same as `git_config_bool`, except that it returns -1 on error rather - * than dying. - */ -int git_parse_maybe_bool(const char *); - /** * Parse the string to an integer, including unit factors. Dies on error; * otherwise, returns the parsed result. @@ -343,8 +333,6 @@ int git_config_rename_section(const char *, const char *); int git_config_rename_section_in_file(const char *, const char *, const char *); int git_config_copy_section(const char *, const char *); int git_config_copy_section_in_file(const char *, const char *, const char *); -int git_env_bool(const char *, int); -unsigned long git_env_ulong(const char *, unsigned long); int git_config_system(void); int config_error_nonbool(const char *); #if defined(__GNUC__) diff --git a/pack-objects.c b/pack-objects.c index 1b8052bece..f403ca6986 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -3,7 +3,7 @@ #include "pack.h" #include "pack-objects.h" #include "packfile.h" -#include "config.h" +#include "parse.h" static uint32_t locate_object_entry_hash(struct packing_data *pdata, const struct object_id *oid, diff --git a/pack-revindex.c b/pack-revindex.c index 7fffcad912..a01a2a4640 100644 --- a/pack-revindex.c +++ b/pack-revindex.c @@ -6,7 +6,7 @@ #include "packfile.h" #include "strbuf.h" #include "trace2.h" -#include "config.h" +#include "parse.h" #include "midx.h" #include "csum-file.h" diff --git a/parse-options.c b/parse-options.c index f8a155ee13..9f542950a7 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1,11 +1,12 @@ #include "git-compat-util.h" #include "parse-options.h" #include "abspath.h" -#include "config.h" +#include "parse.h" #include "commit.h" #include "color.h" #include "gettext.h" #include "strbuf.h" +#include "string-list.h" #include "utf8.h" static int disallow_abbreviated_options; diff --git a/parse.c b/parse.c new file mode 100644 index 0000000000..42d691a0fb --- /dev/null +++ b/parse.c @@ -0,0 +1,182 @@ +#include "git-compat-util.h" +#include "gettext.h" +#include "parse.h" + +static uintmax_t get_unit_factor(const char *end) +{ + if (!*end) + return 1; + else if (!strcasecmp(end, "k")) + return 1024; + else if (!strcasecmp(end, "m")) + return 1024 * 1024; + else if (!strcasecmp(end, "g")) + return 1024 * 1024 * 1024; + return 0; +} + +int git_parse_signed(const char *value, intmax_t *ret, intmax_t max) +{ + if (value && *value) { + char *end; + intmax_t val; + intmax_t factor; + + if (max < 0) + BUG("max must be a positive integer"); + + errno = 0; + val = strtoimax(value, &end, 0); + if (errno == ERANGE) + return 0; + if (end == value) { + errno = EINVAL; + return 0; + } + factor = get_unit_factor(end); + if (!factor) { + errno = EINVAL; + return 0; + } + if ((val < 0 && -max / factor > val) || + (val > 0 && max / factor < val)) { + errno = ERANGE; + return 0; + } + val *= factor; + *ret = val; + return 1; + } + errno = EINVAL; + return 0; +} + +static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max) +{ + if (value && *value) { + char *end; + uintmax_t val; + uintmax_t factor; + + /* negative values would be accepted by strtoumax */ + if (strchr(value, '-')) { + errno = EINVAL; + return 0; + } + errno = 0; + val = strtoumax(value, &end, 0); + if (errno == ERANGE) + return 0; + if (end == value) { + errno = EINVAL; + return 0; + } + factor = get_unit_factor(end); + if (!factor) { + errno = EINVAL; + return 0; + } + if (unsigned_mult_overflows(factor, val) || + factor * val > max) { + errno = ERANGE; + return 0; + } + val *= factor; + *ret = val; + return 1; + } + errno = EINVAL; + return 0; +} + +int git_parse_int(const char *value, int *ret) +{ + intmax_t tmp; + if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int))) + return 0; + *ret = tmp; + return 1; +} + +int git_parse_int64(const char *value, int64_t *ret) +{ + intmax_t tmp; + if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t))) + return 0; + *ret = tmp; + return 1; +} + +int git_parse_ulong(const char *value, unsigned long *ret) +{ + uintmax_t tmp; + if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long))) + return 0; + *ret = tmp; + return 1; +} + +int git_parse_ssize_t(const char *value, ssize_t *ret) +{ + intmax_t tmp; + if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(ssize_t))) + return 0; + *ret = tmp; + return 1; +} + +int git_parse_maybe_bool_text(const char *value) +{ + if (!value) + return 1; + if (!*value) + return 0; + if (!strcasecmp(value, "true") + || !strcasecmp(value, "yes") + || !strcasecmp(value, "on")) + return 1; + if (!strcasecmp(value, "false") + || !strcasecmp(value, "no") + || !strcasecmp(value, "off")) + return 0; + return -1; +} + +int git_parse_maybe_bool(const char *value) +{ + int v = git_parse_maybe_bool_text(value); + if (0 <= v) + return v; + if (git_parse_int(value, &v)) + return !!v; + return -1; +} + +/* + * Parse environment variable 'k' as a boolean (in various + * possible spellings); if missing, use the default value 'def'. + */ +int git_env_bool(const char *k, int def) +{ + const char *v = getenv(k); + int val; + if (!v) + return def; + val = git_parse_maybe_bool(v); + if (val < 0) + die(_("bad boolean environment value '%s' for '%s'"), + v, k); + return val; +} + +/* + * Parse environment variable 'k' as ulong with possibly a unit + * suffix; if missing, use the default value 'val'. + */ +unsigned long git_env_ulong(const char *k, unsigned long val) +{ + const char *v = getenv(k); + if (v && !git_parse_ulong(v, &val)) + die(_("failed to parse %s"), k); + return val; +} diff --git a/parse.h b/parse.h new file mode 100644 index 0000000000..07d2193d69 --- /dev/null +++ b/parse.h @@ -0,0 +1,20 @@ +#ifndef PARSE_H +#define PARSE_H + +int git_parse_signed(const char *value, intmax_t *ret, intmax_t max); +int git_parse_ssize_t(const char *, ssize_t *); +int git_parse_ulong(const char *, unsigned long *); +int git_parse_int(const char *value, int *ret); +int git_parse_int64(const char *value, int64_t *ret); + +/** + * Same as `git_config_bool`, except that it returns -1 on error rather + * than dying. + */ +int git_parse_maybe_bool(const char *); +int git_parse_maybe_bool_text(const char *value); + +int git_env_bool(const char *, int); +unsigned long git_env_ulong(const char *, unsigned long); + +#endif /* PARSE_H */ diff --git a/pathspec.c b/pathspec.c index 4991455281..39337999d4 100644 --- a/pathspec.c +++ b/pathspec.c @@ -1,6 +1,6 @@ #include "git-compat-util.h" #include "abspath.h" -#include "config.h" +#include "parse.h" #include "dir.h" #include "environment.h" #include "gettext.h" diff --git a/preload-index.c b/preload-index.c index e44530c80c..63fd35d64b 100644 --- a/preload-index.c +++ b/preload-index.c @@ -7,7 +7,7 @@ #include "environment.h" #include "fsmonitor.h" #include "gettext.h" -#include "config.h" +#include "parse.h" #include "preload-index.h" #include "progress.h" #include "read-cache.h" diff --git a/progress.c b/progress.c index f695798aca..c83cb60bf1 100644 --- a/progress.c +++ b/progress.c @@ -17,7 +17,7 @@ #include "trace.h" #include "trace2.h" #include "utf8.h" -#include "config.h" +#include "parse.h" #define TP_IDX_MAX 8 diff --git a/prompt.c b/prompt.c index 3baa33f63d..8935fe4dfb 100644 --- a/prompt.c +++ b/prompt.c @@ -1,5 +1,5 @@ #include "git-compat-util.h" -#include "config.h" +#include "parse.h" #include "environment.h" #include "run-command.h" #include "strbuf.h" diff --git a/rebase.c b/rebase.c index 17a570f1ff..69a1822da3 100644 --- a/rebase.c +++ b/rebase.c @@ -1,6 +1,6 @@ #include "git-compat-util.h" #include "rebase.h" -#include "config.h" +#include "parse.h" #include "gettext.h" /* diff --git a/t/helper/test-env-helper.c b/t/helper/test-env-helper.c index 66c88b8ff3..1c486888a4 100644 --- a/t/helper/test-env-helper.c +++ b/t/helper/test-env-helper.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "config.h" +#include "parse.h" #include "parse-options.h" static char const * const env__helper_usage[] = { diff --git a/unpack-trees.c b/unpack-trees.c index 87517364dc..761562a96e 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -2,7 +2,7 @@ #include "advice.h" #include "strvec.h" #include "repository.h" -#include "config.h" +#include "parse.h" #include "dir.h" #include "environment.h" #include "gettext.h" diff --git a/wrapper.c b/wrapper.c index 118d3033de..a6249cc30e 100644 --- a/wrapper.c +++ b/wrapper.c @@ -3,7 +3,7 @@ */ #include "git-compat-util.h" #include "abspath.h" -#include "config.h" +#include "parse.h" #include "gettext.h" #include "repository.h" #include "strbuf.h" diff --git a/write-or-die.c b/write-or-die.c index d8355c0c3e..42a2dc73cd 100644 --- a/write-or-die.c +++ b/write-or-die.c @@ -1,5 +1,5 @@ #include "git-compat-util.h" -#include "config.h" +#include "parse.h" #include "run-command.h" #include "write-or-die.h" From patchwork Thu Aug 10 16:36:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349731 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E548C04E69 for ; Thu, 10 Aug 2023 16:38:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233077AbjHJQiO (ORCPT ); Thu, 10 Aug 2023 12:38:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235935AbjHJQhb (ORCPT ); Thu, 10 Aug 2023 12:37:31 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6D402D7F for ; Thu, 10 Aug 2023 09:37:19 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-564fec87e4fso1423733a12.0 for ; Thu, 10 Aug 2023 09:37:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685439; x=1692290239; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=xg6X9acYqDxAbpbyRKoaikCwIC1ixFALe5UD9PsE4qA=; b=lG3oKi5SNxaJpbPlYNXyiHjADbXCFoze7AEmZ2rV7s6RmzG6GWwxJKW8fTB5mtEHP5 6gnPlQtnTeQ+kWLkKeFfkqMvu7oVFwvNuc1G4Iih3/CfXej2iptaOnBhSJhjZBZ/BgS8 YP9UZwOJj55+CHtMTBuAmJmL7ehM/rmZ7Go8ZQ/pTanS3Bwx9QjAzcmFglBL6QAhPgt8 MZDb8aNp6SA5dVaUBV+3rCLDkrhfqGxtvfTQQuVdtigfGRjhOJ5UCgALqIkB9tlfok84 gFggpD5M/oxVgMmV9OPBMoWAlHjeaNEER3WSeE/xtKHzCDyFVtS3Y+dRhqyZItxJggBy 32Pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685439; x=1692290239; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=xg6X9acYqDxAbpbyRKoaikCwIC1ixFALe5UD9PsE4qA=; b=AInBN9rwfySJ10usIsEIWhRhymVl2MDRoA0IUGKmeJ+fpAy3n3U8oOEGUa0DsYxKF+ btFkfUAR8D6uewV3mD9HqZsaoBIFHzs2w65sdqOADLf2ecKhkW58f50KcIH9Jo4JldjW VlhUHEhtNNUzzRqU+fj0B3jV4zhSgoa/tWp8+i5tHPx4QdFHlllmA1nCXsdi5Jh8XM3c r901gyN+FOtQpF2JaCeaewVsxWGLUQVB/8C5Z/mNAJEWsBekCYE2sjrfKCMWy5Fbrx5D aICkBOZkFlXvCdWBBx/oPUnBEetsppwt+NNoqsDEcITcUrHqfOCo7lf0yFpGtZuHy1uO WnDQ== X-Gm-Message-State: AOJu0Ywn1M1ZSTWrjEmm7qYLasIjAIDY58wDonFLg10lvQU/wgheiO63 WdNwrAueQBJ+HBOEHD3caizxgphFucPv09WU58GDIX9CEPohDw+g+rthWBdG+pH+2ixNmM4EeHM WkB+UQbcFm3wwonffn0XsDygoWaDgKvpNJHOitDEustsgW2LxKe+vvwoshff6q2sr5Q== X-Google-Smtp-Source: AGHT+IFf+7EWZqOhfET8+xzB5ng3QsolvfBONpJ3P+cE+aX4ff9VfyWNL3aDXqocK3QMw+TzLCZOVV9nOa7bGgs= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a63:770f:0:b0:55f:d4a4:57ba with SMTP id s15-20020a63770f000000b0055fd4a457bamr207452pgc.8.1691685439207; Thu, 10 Aug 2023 09:37:19 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:52 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-5-calvinwan@google.com> Subject: [RFC PATCH v2 5/7] date: push pager.h dependency up From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org In order for date.c to be included in git-std-lib, the dependency to pager.h must be removed since it has dependencies on many other files not in git-std-lib. We achieve this by passing a boolean for "pager_in_use", rather than checking for it in parse_date_format() so callers of the function will have that dependency. Signed-off-by: Calvin Wan --- builtin/blame.c | 2 +- builtin/log.c | 2 +- date.c | 5 ++--- date.h | 2 +- ref-filter.c | 3 ++- revision.c | 3 ++- t/helper/test-date.c | 3 ++- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/builtin/blame.c b/builtin/blame.c index 9a3f9facea..665511570d 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -714,7 +714,7 @@ static int git_blame_config(const char *var, const char *value, void *cb) if (!strcmp(var, "blame.date")) { if (!value) return config_error_nonbool(var); - parse_date_format(value, &blame_date_mode); + parse_date_format(value, &blame_date_mode, pager_in_use()); return 0; } if (!strcmp(var, "blame.ignorerevsfile")) { diff --git a/builtin/log.c b/builtin/log.c index 03954fb749..a72ce30c2e 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -185,7 +185,7 @@ static void cmd_log_init_defaults(struct rev_info *rev) rev->diffopt.flags.allow_textconv = 1; if (default_date_mode) - parse_date_format(default_date_mode, &rev->date_mode); + parse_date_format(default_date_mode, &rev->date_mode, pager_in_use()); } static void set_default_decoration_filter(struct decoration_filter *decoration_filter) diff --git a/date.c b/date.c index 619ada5b20..55f73ce2e0 100644 --- a/date.c +++ b/date.c @@ -7,7 +7,6 @@ #include "git-compat-util.h" #include "date.h" #include "gettext.h" -#include "pager.h" #include "strbuf.h" /* @@ -1003,13 +1002,13 @@ static enum date_mode_type parse_date_type(const char *format, const char **end) die("unknown date format %s", format); } -void parse_date_format(const char *format, struct date_mode *mode) +void parse_date_format(const char *format, struct date_mode *mode, int pager_in_use) { const char *p; /* "auto:foo" is "if tty/pager, then foo, otherwise normal" */ if (skip_prefix(format, "auto:", &p)) { - if (isatty(1) || pager_in_use()) + if (isatty(1) || pager_in_use) format = p; else format = "default"; diff --git a/date.h b/date.h index 6136212a19..d9bd6dc09f 100644 --- a/date.h +++ b/date.h @@ -53,7 +53,7 @@ const char *show_date(timestamp_t time, int timezone, const struct date_mode *mo * be used with strbuf_addftime(), in which case you'll need to call * date_mode_release() later. */ -void parse_date_format(const char *format, struct date_mode *mode); +void parse_date_format(const char *format, struct date_mode *mode, int pager_in_use); /** * Release a "struct date_mode", currently only required if diff --git a/ref-filter.c b/ref-filter.c index 2ed0ecf260..1b96bb7822 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -28,6 +28,7 @@ #include "worktree.h" #include "hashmap.h" #include "strvec.h" +#include "pager.h" static struct ref_msg { const char *gone; @@ -1323,7 +1324,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam formatp = strchr(atomname, ':'); if (formatp) { formatp++; - parse_date_format(formatp, &date_mode); + parse_date_format(formatp, &date_mode, pager_in_use()); } if (!eoemail) diff --git a/revision.c b/revision.c index 985b8b2f51..c7efd11914 100644 --- a/revision.c +++ b/revision.c @@ -46,6 +46,7 @@ #include "resolve-undo.h" #include "parse-options.h" #include "wildmatch.h" +#include "pager.h" volatile show_early_output_fn_t show_early_output; @@ -2577,7 +2578,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->date_mode.type = DATE_RELATIVE; revs->date_mode_explicit = 1; } else if ((argcount = parse_long_opt("date", argv, &optarg))) { - parse_date_format(optarg, &revs->date_mode); + parse_date_format(optarg, &revs->date_mode, pager_in_use()); revs->date_mode_explicit = 1; return argcount; } else if (!strcmp(arg, "--log-size")) { diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 0683d46574..b3927a95b3 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -1,5 +1,6 @@ #include "test-tool.h" #include "date.h" +#include "pager.h" #include "trace.h" static const char *usage_msg = "\n" @@ -37,7 +38,7 @@ static void show_dates(const char **argv, const char *format) { struct date_mode mode = DATE_MODE_INIT; - parse_date_format(format, &mode); + parse_date_format(format, &mode, pager_in_use()); for (; *argv; argv++) { char *arg; timestamp_t t; From patchwork Thu Aug 10 16:36:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349734 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F40BC04FDF for ; Thu, 10 Aug 2023 16:38:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235873AbjHJQiS (ORCPT ); Thu, 10 Aug 2023 12:38:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34660 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236033AbjHJQhe (ORCPT ); Thu, 10 Aug 2023 12:37:34 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBC9B30CA for ; Thu, 10 Aug 2023 09:37:21 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-586a5cd0ea9so14281777b3.2 for ; Thu, 10 Aug 2023 09:37:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685441; x=1692290241; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5cUxUi4uBhpupqkYaatpzJKbvNJPyRHJkk6V+qr5Vb4=; b=G+LsoA+yudAStO6f55w5mi0OOi/6J7MFiC3LnGIYr4hPJvfsj43BEaDIsPkuYbXRcQ +QaHC0HzdPYhjhXYHTLhys8vEURtahqzXHecK+OzEAQqAO+N7r2OFcN5h/Wg5tjMIucy ar5va2SDAx8dN0H8pFmYK4enaAiMtCOUqy97buKyEPRlH5s9gnBWlkQ3qFod8qoJU5IB brkIRWKDTgXYe7o1Z1gAXcO8tFBgvzkKCziXL8S0uHUGRJrpturQ1WIu4ZGCZf5egwwN lh37Fqa1lPDYG4VP/nlBHIdiPyImGnREzub8+33ITTdaCLf0DceJegt6mQNkQ1eGbP49 DX1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685441; x=1692290241; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5cUxUi4uBhpupqkYaatpzJKbvNJPyRHJkk6V+qr5Vb4=; b=OoLwjpwPVfzkwu9jHcZd7CMp+z5jGQeQ3LBBsg/VMLaTEOHeCp9e8b+wCI4wD6HIjl 6zLB6/YWXWPybmM8hSlQvYQYJLjmMojhYtTKGY08UXdhPz3og/8YG3O7/ye9mrA+tedb Ztd4GJXpHtk60vYN+H4/sHGQRt7G3BqSSkYiNYrTliBLBD/AFDWDExWTklwOgcs5sp77 1jaaq8V9NLSv2NnmkLNXrTdL02TWi2Tog9jWGWx+UhlX1Ea4jhgYx/mIu3vu3M2Y8lKu waLSkJb+8Hev11JpHT5ZmqswgJdDELy6fmSeA/x4Pve8kebDs6hiN0c85fqqG4ZhW4k6 AvYg== X-Gm-Message-State: AOJu0YyX5D6nFL/B3jp7j67y0i5oWLd+UdlhU1+T4CneKAv8E3H4D3u2 StISLv9wJKJnLreIVGN4EOSnzMxwbd1ApAWx6nTFFs1qqQgU7U/MR/7e4kMieeV6Xee1npNjqnS 9HvnnHGueY1HLnPt58eWdkWoxmt81vNIbRQpcQMiu0c+JMGcJNdNCsBO/eEZ2NUxB+w== X-Google-Smtp-Source: AGHT+IHiPfVp2BF6m8O/k45+/sm2R70tM0MzJtCvVtx/9XzyyhLCF5TKmvcUs+2OGr6DsmRcKqY1VRGG9OMiWtg= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a25:340a:0:b0:d0c:e71d:fab with SMTP id b10-20020a25340a000000b00d0ce71d0fabmr51740yba.0.1691685440927; Thu, 10 Aug 2023 09:37:20 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:53 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-6-calvinwan@google.com> Subject: [RFC PATCH v2 6/7] git-std-lib: introduce git standard library From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The Git Standard Library intends to serve as the foundational library and root dependency that other libraries in Git will be built off of. That is to say, suppose we have libraries X and Y; a user that wants to use X and Y would need to include X, Y, and this Git Standard Library. Add Documentation/technical/git-std-lib.txt to further explain the design and rationale. Signed-off-by: Calvin Wan --- Documentation/technical/git-std-lib.txt | 186 ++++++++++++++++++++++++ Makefile | 62 +++++++- git-compat-util.h | 7 +- stubs/repository.c | 4 + stubs/repository.h | 8 + stubs/trace2.c | 22 +++ stubs/trace2.h | 69 +++++++++ symlinks.c | 2 + 8 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 Documentation/technical/git-std-lib.txt create mode 100644 stubs/repository.c create mode 100644 stubs/repository.h create mode 100644 stubs/trace2.c create mode 100644 stubs/trace2.h diff --git a/Documentation/technical/git-std-lib.txt b/Documentation/technical/git-std-lib.txt new file mode 100644 index 0000000000..3d901a89b0 --- /dev/null +++ b/Documentation/technical/git-std-lib.txt @@ -0,0 +1,186 @@ +Git Standard Library +================ + +The Git Standard Library intends to serve as the foundational library +and root dependency that other libraries in Git will be built off of. +That is to say, suppose we have libraries X and Y; a user that wants to +use X and Y would need to include X, Y, and this Git Standard Library. +This does not mean that the Git Standard Library will be the only +possible root dependency in the future, but rather the most significant +and widely used one. + +Dependency graph in libified Git +================ + +If you look in the Git Makefile, all of the objects defined in the Git +library are compiled and archived into a singular file, libgit.a, which +is linked against by common-main.o with other external dependencies and +turned into the Git executable. In other words, the Git executable has +dependencies on libgit.a and a couple of external libraries. The +libfication of Git will not affect this current build flow, but instead +will provide an alternate method for building Git. + +With our current method of building Git, we can imagine the dependency +graph as such: + + Git + /\ + / \ + / \ + libgit.a ext deps + +In libifying parts of Git, we want to shrink the dependency graph to +only the minimal set of dependencies, so libraries should not use +libgit.a. Instead, it would look like: + + Git + /\ + / \ + / \ + libgit.a ext deps + /\ + / \ + / \ +object-store.a (other lib) + | / + | / + | / + config.a / + | / + | / + | / +git-std-lib.a + +Instead of containing all of the objects in Git, libgit.a would contain +objects that are not built by libraries it links against. Consequently, +if someone wanted their own custom build of Git with their own custom +implementation of the object store, they would only have to swap out +object-store.a rather than do a hard fork of Git. + +Rationale behind Git Standard Library +================ + +The rationale behind Git Standard Library essentially is the result of +two observations within the Git codebase: every file includes +git-compat-util.h which defines functions in a couple of different +files, and wrapper.c + usage.c have difficult-to-separate circular +dependencies with each other and other files. + +Ubiquity of git-compat-util.h and circular dependencies +======== + +Every file in the Git codebase includes git-compat-util.h. It serves as +"a compatibility aid that isolates the knowledge of platform specific +inclusion order and what feature macros to define before including which +system header" (Junio[1]). Since every file includes git-compat-util.h, and +git-compat-util.h includes wrapper.h and usage.h, it would make sense +for wrapper.c and usage.c to be a part of the root library. They have +difficult to separate circular dependencies with each other so they +can't be independent libraries. Wrapper.c has dependencies on parse.c, +abspath.c, strbuf.c, which in turn also have dependencies on usage.c and +wrapper.c -- more circular dependencies. + +Tradeoff between swappability and refactoring +======== + +From the above dependency graph, we can see that git-std-lib.a could be +many smaller libraries rather than a singular library. So why choose a +singular library when multiple libraries can be individually easier to +swap and are more modular? A singular library requires less work to +separate out circular dependencies within itself so it becomes a +tradeoff question between work and reward. While there may be a point in +the future where a file like usage.c would want its own library so that +someone can have custom die() or error(), the work required to refactor +out the circular dependencies in some files would be enormous due to +their ubiquity so therefore I believe it is not worth the tradeoff +currently. Additionally, we can in the future choose to do this refactor +and change the API for the library if there becomes enough of a reason +to do so (remember we are avoiding promising stability of the interfaces +of those libraries). + +Reuse of compatibility functions in git-compat-util.h +======== + +Most functions defined in git-compat-util.h are implemented in compat/ +and have dependencies limited to strbuf.h and wrapper.h so they can be +easily included in git-std-lib.a, which as a root dependency means that +higher level libraries do not have to worry about compatibility files in +compat/. The rest of the functions defined in git-compat-util.h are +implemented in top level files and are hidden behind +an #ifdef if their implementation is not in git-std-lib.a. + +Rationale summary +======== + +The Git Standard Library allows us to get the libification ball rolling +with other libraries in Git. By not spending many +more months attempting to refactor difficult circular dependencies and +instead spending that time getting to a state where we can test out +swapping a library out such as config or object store, we can prove the +viability of Git libification on a much faster time scale. Additionally +the code cleanups that have happened so far have been minor and +beneficial for the codebase. It is probable that making large movements +would negatively affect code clarity. + +Git Standard Library boundary +================ + +While I have described above some useful heuristics for identifying +potential candidates for git-std-lib.a, a standard library should not +have a shaky definition for what belongs in it. + + - Low-level files (aka operates only on other primitive types) that are + used everywhere within the codebase (wrapper.c, usage.c, strbuf.c) + - Dependencies that are low-level and widely used + (abspath.c, date.c, hex-ll.c, parse.c, utf8.c) + - low-level git/* files with functions defined in git-compat-util.h + (ctype.c) + - compat/* + - stubbed out dependencies in stubs/ (stubs/repository.c, stubs/trace2.c) + +There are other files that might fit this definition, but that does not +mean it should belong in git-std-lib.a. Those files should start as +their own separate library since any file added to git-std-lib.a loses +its flexibility of being easily swappable. + +Wrapper.c and usage.c have dependencies on repository and trace2 that are +possible to remove at the cost of sacrificing the ability for standard Git +to be able to trace functions in those files and other files in git-std-lib.a. +In order for git-std-lib.a to compile with those dependencies, stubbed out +versions of those files are implemented and swapped in during compilation time. + +Files inside of Git Standard Library +================ + +The initial set of files in git-std-lib.a are: +abspath.c +ctype.c +date.c +hex-ll.c +parse.c +strbuf.c +usage.c +utf8.c +wrapper.c +stubs/repository.c +stubs/trace2.c +relevant compat/ files + +Pitfalls +================ + +There are a small amount of files under compat/* that have dependencies +not inside of git-std-lib.a. While those functions are not called on +Linux, other OSes might call those problematic functions. I don't see +this as a major problem, just moreso an observation that libification in +general may also require some minor compatibility work in the future. + +Testing +================ + +Unit tests should catch any breakages caused by changes to files in +git-std-lib.a (i.e. introduction of a out of scope dependency) and new +functions introduced to git-std-lib.a will require unit tests written +for them. + +[1] https://lore.kernel.org/git/xmqqwn17sydw.fsf@gitster.g/ \ No newline at end of file diff --git a/Makefile b/Makefile index e9ad9f9ef1..82510cf50e 100644 --- a/Makefile +++ b/Makefile @@ -669,6 +669,7 @@ FUZZ_PROGRAMS = GIT_OBJS = LIB_OBJS = SCALAR_OBJS = +STUB_OBJS = OBJECTS = OTHER_PROGRAMS = PROGRAM_OBJS = @@ -956,6 +957,7 @@ COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES)) LIB_H = $(FOUND_H_SOURCES) +ifndef GIT_STD_LIB LIB_OBJS += abspath.o LIB_OBJS += add-interactive.o LIB_OBJS += add-patch.o @@ -1196,6 +1198,27 @@ LIB_OBJS += write-or-die.o LIB_OBJS += ws.o LIB_OBJS += wt-status.o LIB_OBJS += xdiff-interface.o +else ifdef GIT_STD_LIB +LIB_OBJS += abspath.o +LIB_OBJS += ctype.o +LIB_OBJS += date.o +LIB_OBJS += hex-ll.o +LIB_OBJS += parse.o +LIB_OBJS += strbuf.o +LIB_OBJS += usage.o +LIB_OBJS += utf8.o +LIB_OBJS += wrapper.o + +ifdef STUB_REPOSITORY +STUB_OBJS += stubs/repository.o +endif + +ifdef STUB_TRACE2 +STUB_OBJS += stubs/trace2.o +endif + +LIB_OBJS += $(STUB_OBJS) +endif BUILTIN_OBJS += builtin/add.o BUILTIN_OBJS += builtin/am.o @@ -2162,6 +2185,11 @@ ifdef FSMONITOR_OS_SETTINGS COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif +ifdef GIT_STD_LIB + BASIC_CFLAGS += -DGIT_STD_LIB + BASIC_CFLAGS += -DNO_GETTEXT +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif @@ -3654,7 +3682,7 @@ clean: profile-clean coverage-clean cocciclean $(RM) po/git.pot po/git-core.pot $(RM) git.res $(RM) $(OBJECTS) - $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB) + $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB) $(STD_LIB_FILE) $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) $(RM) $(TEST_PROGRAMS) $(RM) $(FUZZ_PROGRAMS) @@ -3834,3 +3862,35 @@ $(FUZZ_PROGRAMS): all $(XDIFF_OBJS) $(EXTLIBS) git.o $@.o $(LIB_FUZZING_ENGINE) -o $@ fuzz-all: $(FUZZ_PROGRAMS) + +### Libified Git rules + +# git-std-lib +# `make git-std-lib GIT_STD_LIB=YesPlease STUB_REPOSITORY=YesPlease STUB_TRACE2=YesPlease` +STD_LIB = git-std-lib.a + +$(STD_LIB): $(LIB_OBJS) $(COMPAT_OBJS) $(STUB_OBJS) + $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ + +TEMP_HEADERS = temp_headers/ + +git-std-lib: +# Move headers to temporary folder and replace them with stubbed headers. +# After building, move headers and stubbed headers back. +ifneq ($(STUB_OBJS),) + mkdir -p $(TEMP_HEADERS); \ + for d in $(STUB_OBJS); do \ + BASE=$${d%.*}; \ + mv $${BASE##*/}.h $(TEMP_HEADERS)$${BASE##*/}.h; \ + mv $${BASE}.h $${BASE##*/}.h; \ + done; \ + $(MAKE) $(STD_LIB); \ + for d in $(STUB_OBJS); do \ + BASE=$${d%.*}; \ + mv $${BASE##*/}.h $${BASE}.h; \ + mv $(TEMP_HEADERS)$${BASE##*/}.h $${BASE##*/}.h; \ + done; \ + rm -rf temp_headers +else + $(MAKE) $(STD_LIB) +endif diff --git a/git-compat-util.h b/git-compat-util.h index 481dac22b0..75aa9b263e 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -396,8 +396,8 @@ static inline int noop_core_config(const char *var UNUSED, #define platform_core_config noop_core_config #endif +#if !defined(__MINGW32__) && !defined(_MSC_VER) && !defined(GIT_STD_LIB) int lstat_cache_aware_rmdir(const char *path); -#if !defined(__MINGW32__) && !defined(_MSC_VER) #define rmdir lstat_cache_aware_rmdir #endif @@ -787,9 +787,11 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size); #endif #ifdef NO_PTHREADS +#ifdef GIT_STD_LIB #define atexit git_atexit int git_atexit(void (*handler)(void)); #endif +#endif /* * Limit size of IO chunks, because huge chunks only cause pain. OS X @@ -951,14 +953,17 @@ int git_access(const char *path, int mode); # endif #endif +#ifndef GIT_STD_LIB int cmd_main(int, const char **); /* * Intercept all calls to exit() and route them to trace2 to * optionally emit a message before calling the real exit(). */ + int common_exit(const char *file, int line, int code); #define exit(code) exit(common_exit(__FILE__, __LINE__, (code))) +#endif /* * You can mark a stack variable with UNLEAK(var) to avoid it being diff --git a/stubs/repository.c b/stubs/repository.c new file mode 100644 index 0000000000..f81520d083 --- /dev/null +++ b/stubs/repository.c @@ -0,0 +1,4 @@ +#include "git-compat-util.h" +#include "repository.h" + +struct repository *the_repository; diff --git a/stubs/repository.h b/stubs/repository.h new file mode 100644 index 0000000000..18262d748e --- /dev/null +++ b/stubs/repository.h @@ -0,0 +1,8 @@ +#ifndef REPOSITORY_H +#define REPOSITORY_H + +struct repository { int stub; }; + +extern struct repository *the_repository; + +#endif /* REPOSITORY_H */ diff --git a/stubs/trace2.c b/stubs/trace2.c new file mode 100644 index 0000000000..efc3f9c1f3 --- /dev/null +++ b/stubs/trace2.c @@ -0,0 +1,22 @@ +#include "git-compat-util.h" +#include "trace2.h" + +void trace2_region_enter_fl(const char *file, int line, const char *category, + const char *label, const struct repository *repo, ...) { } +void trace2_region_leave_fl(const char *file, int line, const char *category, + const char *label, const struct repository *repo, ...) { } +void trace2_data_string_fl(const char *file, int line, const char *category, + const struct repository *repo, const char *key, + const char *value) { } +void trace2_cmd_ancestry_fl(const char *file, int line, const char **parent_names) { } +void trace2_cmd_error_va_fl(const char *file, int line, const char *fmt, + va_list ap) { } +void trace2_cmd_name_fl(const char *file, int line, const char *name) { } +void trace2_thread_start_fl(const char *file, int line, + const char *thread_base_name) { } +void trace2_thread_exit_fl(const char *file, int line) { } +void trace2_data_intmax_fl(const char *file, int line, const char *category, + const struct repository *repo, const char *key, + intmax_t value) { } +int trace2_is_enabled(void) { return 0; } +void trace2_collect_process_info(enum trace2_process_info_reason reason) { } diff --git a/stubs/trace2.h b/stubs/trace2.h new file mode 100644 index 0000000000..88ad7387ff --- /dev/null +++ b/stubs/trace2.h @@ -0,0 +1,69 @@ +#ifndef TRACE2_H +#define TRACE2_H + +struct child_process { int stub; }; +struct repository; +struct json_writer { int stub; }; + +void trace2_region_enter_fl(const char *file, int line, const char *category, + const char *label, const struct repository *repo, ...); + +#define trace2_region_enter(category, label, repo) \ + trace2_region_enter_fl(__FILE__, __LINE__, (category), (label), (repo)) + +void trace2_region_leave_fl(const char *file, int line, const char *category, + const char *label, const struct repository *repo, ...); + +#define trace2_region_leave(category, label, repo) \ + trace2_region_leave_fl(__FILE__, __LINE__, (category), (label), (repo)) + +void trace2_data_string_fl(const char *file, int line, const char *category, + const struct repository *repo, const char *key, + const char *value); + +#define trace2_data_string(category, repo, key, value) \ + trace2_data_string_fl(__FILE__, __LINE__, (category), (repo), (key), \ + (value)) + +void trace2_cmd_ancestry_fl(const char *file, int line, const char **parent_names); + +#define trace2_cmd_ancestry(v) trace2_cmd_ancestry_fl(__FILE__, __LINE__, (v)) + +void trace2_cmd_error_va_fl(const char *file, int line, const char *fmt, + va_list ap); + +#define trace2_cmd_error_va(fmt, ap) \ + trace2_cmd_error_va_fl(__FILE__, __LINE__, (fmt), (ap)) + + +void trace2_cmd_name_fl(const char *file, int line, const char *name); + +#define trace2_cmd_name(v) trace2_cmd_name_fl(__FILE__, __LINE__, (v)) + +void trace2_thread_start_fl(const char *file, int line, + const char *thread_base_name); + +#define trace2_thread_start(thread_base_name) \ + trace2_thread_start_fl(__FILE__, __LINE__, (thread_base_name)) + +void trace2_thread_exit_fl(const char *file, int line); + +#define trace2_thread_exit() trace2_thread_exit_fl(__FILE__, __LINE__) + +void trace2_data_intmax_fl(const char *file, int line, const char *category, + const struct repository *repo, const char *key, + intmax_t value); + +#define trace2_data_intmax(category, repo, key, value) \ + trace2_data_intmax_fl(__FILE__, __LINE__, (category), (repo), (key), \ + (value)) + +enum trace2_process_info_reason { + TRACE2_PROCESS_INFO_STARTUP, + TRACE2_PROCESS_INFO_EXIT, +}; +int trace2_is_enabled(void); +void trace2_collect_process_info(enum trace2_process_info_reason reason); + +#endif /* TRACE2_H */ + diff --git a/symlinks.c b/symlinks.c index b29e340c2d..bced721a0c 100644 --- a/symlinks.c +++ b/symlinks.c @@ -337,6 +337,7 @@ void invalidate_lstat_cache(void) reset_lstat_cache(&default_cache); } +#if !defined(__MINGW32__) && !defined(_MSC_VER) && !defined(GIT_STD_LIB) #undef rmdir int lstat_cache_aware_rmdir(const char *path) { @@ -348,3 +349,4 @@ int lstat_cache_aware_rmdir(const char *path) return ret; } +#endif From patchwork Thu Aug 10 16:36:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13349733 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E513C41513 for ; Thu, 10 Aug 2023 16:38:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235919AbjHJQiU (ORCPT ); Thu, 10 Aug 2023 12:38:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236128AbjHJQhe (ORCPT ); Thu, 10 Aug 2023 12:37:34 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3FEB30D3 for ; Thu, 10 Aug 2023 09:37:23 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-58419550c3aso14772407b3.0 for ; Thu, 10 Aug 2023 09:37:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691685443; x=1692290243; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=DeeSCGVal+lLSyuK1TBxWJ3N0STmynS4GPGYpM/R5aE=; b=xQHv6LtNAmWuvXZ+TJYLAcgE0H8w/1OiSh2NX6j4CKkg6ezep2TSIabWMLpDCdpg6k JOTYUTWk9u0Y4I4sh8wIwudUfdaGol1CLncADROuBkQSQ1gE4Zx5FgaWOPmzoS1afcDy GiczmPuaeZdvFO9D1Qm9TleN45bmey0UP6S5tVDyh9RyGUS51x+iUB7ohpGQeNLqo8OL rxiZG0R7/eUJhrHkZz591CjNtecsq6zbBwq+IvXmLVJzayBIpogke7+yyUJcZAsbTJ9b ddBUudniXxvlZcVM+oZk2scdk91In3zbEX6cwThq3Cbe4JNaxjJdeteYFJaUdTakLcg9 4hjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691685443; x=1692290243; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=DeeSCGVal+lLSyuK1TBxWJ3N0STmynS4GPGYpM/R5aE=; b=P0sQIoXUhiuTwehQqIxXF4nWFPnXGQ8vy50ClWbDTPqkOLm7rfc/Q4kVFwACOxY/fq AmgRxJJ5hu89iBSezchMOYD4gF5cTps14AdnYl70Mg1szSyxHNZIGrXASWfXdLRV6qbe oMYTBW2+C7lFkeEaLQdX3YedS2jEoSyNoG+KfZTZSf9v2/uq9Sc0XjHo0JWzXjWGna+C YvHqwZ+LwAUw5ngYlixRa/P/E5VKFNKsp/AE3BqglQGb8o8PGeyAZvnI019sA38LirJa hHKwda/xPE0tgdzTFhMHDMK+RgdPhNuTCGIyBCG4cooN2EYRaiF5Z2VT8Ryr3BQlsys3 MBHA== X-Gm-Message-State: AOJu0YyeJ77NBAMMl7mX7VMtWdMaR/whFtJoXRbq1sPSoQ2P2e9g7NQi Et7UrDOh7mZOy1dK+/Y3r2l0J8aoVmLC2VQ2qcTFQlm0ezqAFQdl7OHnHNFCBtvk8sN244Ttl0H +eAeYaUTG9oGWIMXQcXz/BRg4u1MHNs9c/AUv7dPx46CnkTOTmAbKummLhOffWZg53Q== X-Google-Smtp-Source: AGHT+IFMxIMICHD+2danBkcFfpAZwBrJ8Q1ejXhKL99ShXmbLBZzWP+JxYIV8mF0BzNX+1x2ByIzFoWuo3mfLP8= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a81:b654:0:b0:56c:e2da:f440 with SMTP id h20-20020a81b654000000b0056ce2daf440mr53736ywk.0.1691685442761; Thu, 10 Aug 2023 09:37:22 -0700 (PDT) Date: Thu, 10 Aug 2023 16:36:54 +0000 In-Reply-To: <20230810163346.274132-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230810163346.274132-1-calvinwan@google.com> X-Mailer: git-send-email 2.41.0.640.ga95def55d0-goog Message-ID: <20230810163654.275023-7-calvinwan@google.com> Subject: [RFC PATCH v2 7/7] git-std-lib: add test file to call git-std-lib.a functions From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@google.com, chooglen@google.com, jonathantanmy@google.com, linusa@google.com, phillip.wood123@gmail.com, vdye@github.com Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Add test file that directly or indirectly calls all functions defined in git-std-lib.a object files to showcase that they do not reference missing objects and that git-std-lib.a can stand on its own. Certain functions that cause the program to exit or are already called by other functions are commented out. TODO: replace with unit tests Signed-off-by: Calvin Wan --- t/Makefile | 4 + t/stdlib-test.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 t/stdlib-test.c diff --git a/t/Makefile b/t/Makefile index 3e00cdd801..b6d0bc9daa 100644 --- a/t/Makefile +++ b/t/Makefile @@ -150,3 +150,7 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint + +test-git-std-lib: + cc -It -o stdlib-test stdlib-test.c -L. -l:../git-std-lib.a + ./stdlib-test diff --git a/t/stdlib-test.c b/t/stdlib-test.c new file mode 100644 index 0000000000..a5d7374e2f --- /dev/null +++ b/t/stdlib-test.c @@ -0,0 +1,239 @@ +#include "../git-compat-util.h" +#include "../abspath.h" +#include "../hex-ll.h" +#include "../parse.h" +#include "../strbuf.h" +#include "../string-list.h" + +/* + * Calls all functions from git-std-lib + * Some inline/trivial functions are skipped + */ + +void abspath_funcs(void) { + struct strbuf sb = STRBUF_INIT; + + fprintf(stderr, "calling abspath functions\n"); + is_directory("foo"); + strbuf_realpath(&sb, "foo", 0); + strbuf_realpath_forgiving(&sb, "foo", 0); + real_pathdup("foo", 0); + absolute_path("foo"); + absolute_pathdup("foo"); + prefix_filename("foo/", "bar"); + prefix_filename_except_for_dash("foo/", "bar"); + is_absolute_path("foo"); + strbuf_add_absolute_path(&sb, "foo"); + strbuf_add_real_path(&sb, "foo"); +} + +void hex_ll_funcs(void) { + unsigned char c; + + fprintf(stderr, "calling hex-ll functions\n"); + + hexval('c'); + hex2chr("A1"); + hex_to_bytes(&c, "A1", 2); +} + +void parse_funcs(void) { + intmax_t foo; + ssize_t foo1 = -1; + unsigned long foo2; + int foo3; + int64_t foo4; + + fprintf(stderr, "calling parse functions\n"); + + git_parse_signed("42", &foo, maximum_signed_value_of_type(int)); + git_parse_ssize_t("42", &foo1); + git_parse_ulong("42", &foo2); + git_parse_int("42", &foo3); + git_parse_int64("42", &foo4); + git_parse_maybe_bool("foo"); + git_parse_maybe_bool_text("foo"); + git_env_bool("foo", 1); + git_env_ulong("foo", 1); +} + +static int allow_unencoded_fn(char ch) { + return 0; +} + +void strbuf_funcs(void) { + struct strbuf *sb = xmalloc(sizeof(void*)); + struct strbuf *sb2 = xmalloc(sizeof(void*)); + struct strbuf sb3 = STRBUF_INIT; + struct string_list list = STRING_LIST_INIT_NODUP; + char *buf = "foo"; + struct strbuf_expand_dict_entry dict[] = { + { "foo", NULL, }, + { "bar", NULL, }, + }; + int fd = open("/dev/null", O_RDONLY); + + fprintf(stderr, "calling strbuf functions\n"); + + starts_with("foo", "bar"); + istarts_with("foo", "bar"); + // skip_to_optional_arg_default(const char *str, const char *prefix, + // const char **arg, const char *def) + strbuf_init(sb, 0); + strbuf_init(sb2, 0); + strbuf_release(sb); + strbuf_attach(sb, strbuf_detach(sb, NULL), 0, 0); // calls strbuf_grow + strbuf_swap(sb, sb2); + strbuf_setlen(sb, 0); + strbuf_trim(sb); // calls strbuf_rtrim, strbuf_ltrim + // strbuf_rtrim() called by strbuf_trim() + // strbuf_ltrim() called by strbuf_trim() + strbuf_trim_trailing_dir_sep(sb); + strbuf_trim_trailing_newline(sb); + strbuf_reencode(sb, "foo", "bar"); + strbuf_tolower(sb); + strbuf_add_separated_string_list(sb, " ", &list); + strbuf_list_free(strbuf_split_buf("foo bar", 8, ' ', -1)); + strbuf_cmp(sb, sb2); + strbuf_addch(sb, 1); + strbuf_splice(sb, 0, 1, "foo", 3); + strbuf_insert(sb, 0, "foo", 3); + // strbuf_vinsertf() called by strbuf_insertf + strbuf_insertf(sb, 0, "%s", "foo"); + strbuf_remove(sb, 0, 1); + strbuf_add(sb, "foo", 3); + strbuf_addbuf(sb, sb2); + strbuf_join_argv(sb, 0, NULL, ' '); + strbuf_addchars(sb, 1, 1); + strbuf_addf(sb, "%s", "foo"); + strbuf_add_commented_lines(sb, "foo", 3, '#'); + strbuf_commented_addf(sb, '#', "%s", "foo"); + // strbuf_vaddf() called by strbuf_addf() + strbuf_expand(sb, "%s", strbuf_expand_literal_cb, NULL); + strbuf_expand(sb, "%s", strbuf_expand_dict_cb, &dict); + // strbuf_expand_literal_cb() called by strbuf_expand() + // strbuf_expand_dict_cb() called by strbuf_expand() + strbuf_addbuf_percentquote(sb, &sb3); + strbuf_add_percentencode(sb, "foo", STRBUF_ENCODE_SLASH); + strbuf_fread(sb, 0, stdin); + strbuf_read(sb, fd, 0); + strbuf_read_once(sb, fd, 0); + strbuf_write(sb, stderr); + strbuf_readlink(sb, "/dev/null", 0); + strbuf_getcwd(sb); + strbuf_getwholeline(sb, stderr, '\n'); + strbuf_appendwholeline(sb, stderr, '\n'); + strbuf_getline(sb, stderr); + strbuf_getline_lf(sb, stderr); + strbuf_getline_nul(sb, stderr); + strbuf_getwholeline_fd(sb, fd, '\n'); + strbuf_read_file(sb, "/dev/null", 0); + strbuf_add_lines(sb, "foo", "bar", 0); + strbuf_addstr_xml_quoted(sb, "foo"); + strbuf_addstr_urlencode(sb, "foo", allow_unencoded_fn); + strbuf_humanise_bytes(sb, 42); + strbuf_humanise_rate(sb, 42); + printf_ln("%s", sb); + fprintf_ln(stderr, "%s", sb); + xstrdup_tolower("foo"); + xstrdup_toupper("foo"); + // xstrvfmt() called by xstrfmt() + xstrfmt("%s", "foo"); + // strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm, + // int tz_offset, int suppress_tz_name) + // strbuf_stripspace(struct strbuf *sb, char comment_line_char) + // strbuf_strip_suffix(struct strbuf *sb, const char *suffix) + // strbuf_strip_file_from_path(struct strbuf *sb) +} + +static void error_builtin(const char *err, va_list params) {} +static void warn_builtin(const char *err, va_list params) {} + +static report_fn error_routine = error_builtin; +static report_fn warn_routine = warn_builtin; + +void usage_funcs(void) { + fprintf(stderr, "calling usage functions\n"); + // Functions that call exit() are commented out + + // usage() + // usagef() + // die() + // die_errno(); + error("foo"); + error_errno("foo"); + die_message("foo"); + die_message_errno("foo"); + warning("foo"); + warning_errno("foo"); + + // set_die_routine(); + get_die_message_routine(); + set_error_routine(error_builtin); + get_error_routine(); + set_warn_routine(warn_builtin); + get_warn_routine(); + // set_die_is_recursing_routine(); +} + +void wrapper_funcs(void) { + void *ptr = xmalloc(1); + int fd = open("/dev/null", O_RDONLY); + struct strbuf sb = STRBUF_INIT; + int mode = 0444; + char host[PATH_MAX], path[PATH_MAX], path1[PATH_MAX]; + xsnprintf(path, sizeof(path), "out-XXXXXX"); + xsnprintf(path1, sizeof(path1), "out-XXXXXX"); + int tmp; + + fprintf(stderr, "calling wrapper functions\n"); + + xstrdup("foo"); + xmalloc(1); + xmallocz(1); + xmallocz_gently(1); + xmemdupz("foo", 3); + xstrndup("foo", 3); + xrealloc(ptr, 2); + xcalloc(1, 1); + xsetenv("foo", "bar", 0); + xopen("/dev/null", O_RDONLY); + xread(fd, &sb, 1); + xwrite(fd, &sb, 1); + xpread(fd, &sb, 1, 0); + xdup(fd); + xfopen("/dev/null", "r"); + xfdopen(fd, "r"); + tmp = xmkstemp(path); + close(tmp); + unlink(path); + tmp = xmkstemp_mode(path1, mode); + close(tmp); + unlink(path1); + xgetcwd(); + fopen_for_writing(path); + fopen_or_warn(path, "r"); + xstrncmpz("foo", "bar", 3); + // xsnprintf() called above + xgethostname(host, 3); + tmp = git_mkstemps_mode(path, 1, mode); + close(tmp); + unlink(path); + tmp = git_mkstemp_mode(path, mode); + close(tmp); + unlink(path); + read_in_full(fd, &sb, 1); + write_in_full(fd, &sb, 1); + pread_in_full(fd, &sb, 1, 0); +} + +int main() { + abspath_funcs(); + hex_ll_funcs(); + parse_funcs(); + strbuf_funcs(); + usage_funcs(); + wrapper_funcs(); + fprintf(stderr, "all git-std-lib functions finished calling\n"); + return 0; +}