From patchwork Fri Sep 8 17:44:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13377749 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 A176BEEB562 for ; Fri, 8 Sep 2023 17:45:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245460AbjIHRpM (ORCPT ); Fri, 8 Sep 2023 13:45:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40302 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244871AbjIHRo7 (ORCPT ); Fri, 8 Sep 2023 13:44:59 -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 5A0291FDF for ; Fri, 8 Sep 2023 10:44:52 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-573e1a0b355so2391129a12.3 for ; Fri, 08 Sep 2023 10:44:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1694195092; x=1694799892; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=wqVl59QBBEAuF7wpef8DmaKL3shAHLyBUSZYA8kCQng=; b=mX58Ogqjp+DYdlU6yJrBTvrDNU1pZkKVWAwagw6gsvWfkxCnxxdcBH+aGV3dQmTWj7 d+3VU1rdxd7S/4x8w0MUk3X17W/u/t8F1vGbzYk3/plJNU1QjipTp60xr1gf3ppEBhNX 3mkNL74xWJVSvBBxCaj5OHczzJRZGtyElxUC94vWKU/5guEz11oZJLwHY90F10cItbdK bWmRgEFmRuDuymhhbPyFUCImiCyMSxzfHT+gvCrVozS67uat6+zd26OO4EIwbWNUJrR/ LKJgYbwszbmem9wZgM5bMuh/1F7vHN3T5gyKK2dLt2Ks6ES/nm2E7tAY10DYHf96roMW UdGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694195092; x=1694799892; 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=wqVl59QBBEAuF7wpef8DmaKL3shAHLyBUSZYA8kCQng=; b=DnsBgXRic7PAAwq/1hAmdEncFrTi7si83K64xXCt6hHYRXGncXwDAL1j2vPzwv8th3 KwEqxowDdtkLDChEDHs5NybYfc7jilPa34xhcYJfKqFb6Cz12px5JFyVqS8zgtBDRJSA XeF5gNbLwSCUe/OCmNLWzhXQJXMrvKkzIbHp1nKhUFFzQZFJpqtMyk4cbP0klGMYkxVp Ym1CBHiF2Gx7VcvTUzx5FD3NWQYQhYunfwHIm3Y2dT/N1Yn0by6Ayzw40n7czSnF9GXN 9jCZX42BwTBktZjEA2aRaenaO3MA/OJtvzMFIR8YPeEQ0xAQhCnXXl+iek2OJFhXUJop 4d0g== X-Gm-Message-State: AOJu0Yx9dF4VnizZonZ9uSsaON/N3b69AGcsZ2ZXJiN3v/5y5ZxRLFvn FsbV1Ivi8xJia5OkyaUccAF09wpoZ70lJf0sTqOCxbw0mKOg/9UjDo4Xeud+jPdd271aUN0UCf6 i4YicvNTS5IWyn3E+Dp/mKj8xh+vxwVcMD/RWphij277thNm3R2a4hFcTb0DPoXnZ3A== X-Google-Smtp-Source: AGHT+IHw71OODATDSAyl5Xiy2CygjPGRLEYHt+9wxVW9EwhSEjH1ilqbt8NNDzC4H2ZY4ORvOwxPS2z/qN6+5kg= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a63:3688:0:b0:573:f74f:7df7 with SMTP id d130-20020a633688000000b00573f74f7df7mr568285pga.11.1694195091670; Fri, 08 Sep 2023 10:44:51 -0700 (PDT) Date: Fri, 8 Sep 2023 17:44:38 +0000 In-Reply-To: <20230908174134.1026823-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230908174134.1026823-1-calvinwan@google.com> X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230908174443.1027716-1-calvinwan@google.com> Subject: [PATCH v3 1/6] hex-ll: split out functionality from hex From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@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 5776309365..861e643708 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 b24b19566b..f663c06ac4 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 01f17fe5c9..d42262bdca 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 87abf66602..e0b83f776f 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 hash (specified by the_hash_algo) in hexadecimal @@ -34,13 +19,6 @@ int get_oid_hex(const char *hex, struct object_id *oid); /* 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 931505363c..a07d2da16d 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 4c9ac6dc5e..7827178d8e 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 1c45f23adf..1d0254abac 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 Fri Sep 8 17:44:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13377748 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 49527EEB560 for ; Fri, 8 Sep 2023 17:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245217AbjIHRpD (ORCPT ); Fri, 8 Sep 2023 13:45:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232496AbjIHRo7 (ORCPT ); Fri, 8 Sep 2023 13:44:59 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E99701FC9 for ; Fri, 8 Sep 2023 10:44:53 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id d2e1a72fcca58-68bf02547dbso3287674b3a.1 for ; Fri, 08 Sep 2023 10:44:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1694195093; x=1694799893; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=s8GT+aljLTzsbDePyseZ/joAWLog4DPSAq/SXT+uXTY=; b=kLMJktt4DDYeSLEja0yPqoQRkDuwKAcGnt6ivz00fjJG7WHwU7R0gf7pZSzoK7gk5u wJhR4zWbndLIqZYU/0u1dViRhvX4ocwk7cAuV4As9TqMrrCv0kPa+7D+KkPIBTnBzZvu /fqA4lW+rsGksqeJ2poiMQGMgO3D2P011eO5Vs35bYhBt4EVnamEOxFvVlAOHEl0DB1B vRiZljZ1HepZuccSlFsOHokTCraiwvWzCf7BV0fGeCAJjls8TQ3FyZQQvjwwe1TOZw/S D8TkAKUa+PcNIzPwYgGe5zVZmVmppGj1m+7lf2AM4ZC9DcEZEr6cl6Z8b8K9hXdKsQSV +enw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694195093; x=1694799893; 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=s8GT+aljLTzsbDePyseZ/joAWLog4DPSAq/SXT+uXTY=; b=T5WRDwneyenDfEwv3ObDnEuE+qL0ZCdns9hnafezcWVf9PjxRsPK+sBV8ESg5IISgO hRQwykMQ4mhpR0uG0lWzl03lPlOu7ujC/cKZ6i0AUyDTJsNlG4yftCUbkCldNFg4MoFM oLH7dnVfR9Eyt2ZwKqnRqk63i4JR/8VFxLIU4fKNp18ViPv4N9KKezgrL5WeiMRewZY0 d/pjCCgSOt7Brysm2aVJ/ZaIXCjLMSLbrdqVFbECkBqsDEj/4pleZ9v8QTLki1PPTzlm ZQU/h1ujqIJEkKpuIekdKCKAxu9Hsrqcuva3xG1BYD64qkqY/ETkJHiStm2CESWoWBIP FJHg== X-Gm-Message-State: AOJu0YwQw1qJ3Pg5LQupbYV2Z65YhzMHFNPZKkiDD7X3fk6nBA4Kw72o Uk7TUJztIo33EDEoFc52r/v7ecTj9RcnBQOUTyb72hic3vSkKdgNmW6E9xiW80tt8IcWsjCOGdC BNo4GcfHd1tf4hkbAIIpGdgmk8ZjAu+Ug6GX3oc2IKk9pH4haHNZ/wCrJm/bSI2wuAg== X-Google-Smtp-Source: AGHT+IGd9+ZyGFYyOavygFsb0i2bb3SqQpC3Lj4mO1n0aKiq3Lav7CXOejzDyHzx+PWhUnmYsxutYb4ND0hRPJw= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a05:6a00:2d19:b0:68e:3c6d:da7a with SMTP id fa25-20020a056a002d1900b0068e3c6dda7amr1284408pfb.4.1694195093336; Fri, 08 Sep 2023 10:44:53 -0700 (PDT) Date: Fri, 8 Sep 2023 17:44:39 +0000 In-Reply-To: <20230908174134.1026823-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230908174134.1026823-1-calvinwan@google.com> X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230908174443.1027716-2-calvinwan@google.com> Subject: [PATCH v3 2/6] wrapper: remove dependency to Git-specific internal file From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@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 wrapper.c to be built independently as part of a smaller library, it cannot have dependencies to other Git specific internals. remove_or_warn() creates an unnecessary dependency to object.h in wrapper.c. Therefore move the function to entry.[ch] which performs changes on the worktree based on the Git-specific file modes in the index. Signed-off-by: Calvin Wan --- entry.c | 5 +++++ entry.h | 6 ++++++ wrapper.c | 6 ------ wrapper.h | 5 ----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/entry.c b/entry.c index 43767f9043..076e97eb89 100644 --- a/entry.c +++ b/entry.c @@ -581,3 +581,8 @@ void unlink_entry(const struct cache_entry *ce, const char *super_prefix) return; schedule_dir_for_removal(ce->name, ce_namelen(ce)); } + +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/entry.h b/entry.h index 7329f918a9..ca3ed35bc0 100644 --- a/entry.h +++ b/entry.h @@ -62,4 +62,10 @@ int fstat_checkout_output(int fd, const struct checkout *state, struct stat *st) void update_ce_after_write(const struct checkout *state, struct cache_entry *ce, struct stat *st); +/* + * 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 /* ENTRY_H */ diff --git a/wrapper.c b/wrapper.c index 48065c4f53..453a20ed99 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" @@ -632,11 +631,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 79c7321bb3..1b2b047ea0 100644 --- a/wrapper.h +++ b/wrapper.h @@ -106,11 +106,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 Fri Sep 8 17:44:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13377750 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 884EAEEB560 for ; Fri, 8 Sep 2023 17:45:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245126AbjIHRpO (ORCPT ); Fri, 8 Sep 2023 13:45:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245447AbjIHRpD (ORCPT ); Fri, 8 Sep 2023 13:45:03 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A67C91FE0 for ; Fri, 8 Sep 2023 10:44:55 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-d7e79ec07b4so2431076276.0 for ; Fri, 08 Sep 2023 10:44:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1694195095; x=1694799895; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=4gq+PIpSuYKXx7X5Mfl46tvFsgyOkQFELo5vNvFD/hA=; b=gg/hoj0Xf1UGw8ifB27FSJb1YjHg1Vxah57Aaby7qAow6BQCirCj0Qj6WqsMnoyg7c LaFQfp3ay+zU0Dl5jVGIwG4BfIOiOZOv5vDV7JyAt96yRzA7SWBWxb1z+EUORgbY/EqD 7EzKKoXz+PIzR4OByqKCMV0zxLEvOh6+8MmQu11ChwGRvds6J89Ydl8s9XrFk1Myzlou GQ7NVUDEsdV/Cqb9qfmqW6rzeLGRTwoyICSCV99+uC4K7EKTumObBM37JdWm+jgyI+WZ tyTqfLYU+UB8SnOr/2Wirjtj8fVJUXKgZe1US5yUmUyc3Mp/Jibuueb0Hu/UXCSmiROg 5dyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694195095; x=1694799895; 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=4gq+PIpSuYKXx7X5Mfl46tvFsgyOkQFELo5vNvFD/hA=; b=W51TGEgFlwBuZCJjc9EzoYvM8K8x3EtoQnu7Y0XnJAGt9s1ocaOMnH49MXxV8ZXxm+ Ex4NgQkNECBxk/SPtV6TULpSjKQo8IuKOpX/ItluwRK1JrZ+Ti5wmmrPefkqxzSbw+zu oF5g/JABjSwP3hEvQuOZlfRdhhYCMhaMYud+5c4WUAGEqS3uNFTR6amQDgezugcy2zoX zeY8bWojUCT1ICxvoARumVosJfiHFOb9VMHSvF4z/GKQiyhNthaCniCbqdFUXXi4z51R JYg8gDCQ3AbdJ6d4AJL1E5kj/XdVVwfYhLnlxJc27q1vdZ3rsz2AoSEAjWOCT1E3bBR4 V8nw== X-Gm-Message-State: AOJu0YzvpqqST5Mm+WWnrmRKYiKEWyX2sV0GYtWa9hZvFcVqJSvxg4ee qGLKC6hZ2cZziF+LmLMESmVOO/QGWIgXf3gz/CCZGfQpWRo6dlc981Q0lFN59xGkl72mJ61C5y4 sryNQdHDRKyr2ie9Yyjs6VAreHxbl6K0L0YrDKSexV5DmolxGV9E9Neu5OtXm4kbm1Q== X-Google-Smtp-Source: AGHT+IFRw4oXtIgZAzVT5aGAfX16frgEzfXqS0FsWxfIK5OgpN0jtuQKhQWzgvQqS65Zf5dLOI8jX097S/AkdTU= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a05:6902:1022:b0:d80:1250:89bb with SMTP id x2-20020a056902102200b00d80125089bbmr73020ybt.7.1694195094824; Fri, 08 Sep 2023 10:44:54 -0700 (PDT) Date: Fri, 8 Sep 2023 17:44:40 +0000 In-Reply-To: <20230908174134.1026823-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230908174134.1026823-1-calvinwan@google.com> X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230908174443.1027716-3-calvinwan@google.com> Subject: [PATCH v3 3/6] config: correct bad boolean env value error message From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@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 3846a37be9..7dde0aaa02 100644 --- a/config.c +++ b/config.c @@ -2133,7 +2133,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 Fri Sep 8 17:44:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13377751 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 EB81BEEB562 for ; Fri, 8 Sep 2023 17:45:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245441AbjIHRpP (ORCPT ); Fri, 8 Sep 2023 13:45:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43056 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245098AbjIHRpD (ORCPT ); Fri, 8 Sep 2023 13:45:03 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1AE6C1FC9 for ; Fri, 8 Sep 2023 10:44:57 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-d74829dd58fso2295142276.1 for ; Fri, 08 Sep 2023 10:44:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1694195096; x=1694799896; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=mCEun3E/pwYZAWIVkC4IHhrRXlp9Q6Tai0uw+cifELk=; b=H+1NTKGeyi5MmzCRuwYkp+jSE0gasgN0FwqWDNFSvSmTdfOWpedkJko0+vcoZNqy+C 5G3rVJuwvimICKYcnTb0Vz/2hwLcpVR2PGiiHi8IcbBT16pZ+lBCnlbPti8OyMq4+xER BYixQB5Iyd9FKMR/9zKa6SSqrxYSQqQR9NZaiuPu89XRyz5TwToq307DtLs5UCR5uivq kDz1APc20ngkkszA4k07kYvRuA6wSSecskGO77oE0v6n5ApNkk8ybeZ8OqZyovU4NF/4 KCwQR81EDPogSktZwm8hqpvB5eSWSxLmSu8P+KFeVQQi+e57UdXMwFbguz/rGmcCZFTZ Du3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694195096; x=1694799896; 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=mCEun3E/pwYZAWIVkC4IHhrRXlp9Q6Tai0uw+cifELk=; b=fTVvB80Mmr5Iq5iPGpUUogBlY1UlAWvFi2rQXcUBtcxbiUbi+yyyksjDAHli8x6V3y NghwpyRN1GaQZF7vreH0Z0NfghStmHJe24dAQT2gJKiUlTymSS9K+IjdL1m8FKziLJC0 aYmG7oZjGIY8r6Zzyykvrq2DiK7njx5Dk+1557fxrMXHqIwkv9evraZf5F6iq0ntTUSq lu6blYotHlzHOXEWLc8WmA+U7EelcUa2oz1qD56aapbuog7QFQIEZZ+FyPpKZF4EVNir WKF0Tr4l9gThdPU6BY52czdn/qxWHlpsgN6/TigbbaG1+UL/5pHLBanC9uQxvv/+Y2gr RobQ== X-Gm-Message-State: AOJu0YwkhXBjOqSnniYArgj8c2Yl/uYejGDw2Qu7gAIUe4fjh/VKLQxQ G+RoGM3tVC32pEkQQF4F9/UcU/n6q3k3ZQhqpjn42dGIJ+gkhpG6aMGCpXtGKGcEswmXUc/qMet fH9iMTWwAjdgg+Ntt3guAJFLlkLj0WeMRRGTy7CI5s6BjP8T4W11rRktYKs0wX3kaOw== X-Google-Smtp-Source: AGHT+IGalFpUKlDlJaGRGQL9ABfoWSKJCsjoauwXFjIhw1W2usrNQlpdEv+XZ7XEeL45pEP6UM2HUmS8hC4nwwo= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a25:ac02:0:b0:d80:eb4:9ca with SMTP id w2-20020a25ac02000000b00d800eb409camr71107ybi.0.1694195096283; Fri, 08 Sep 2023 10:44:56 -0700 (PDT) Date: Fri, 8 Sep 2023 17:44:41 +0000 In-Reply-To: <20230908174134.1026823-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230908174134.1026823-1-calvinwan@google.com> X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230908174443.1027716-4-calvinwan@google.com> Subject: [PATCH v3 4/6] parse: create new library for parsing strings and env values From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@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. This ultimately allows us to inclue parse.[ch] in an independent library since it doesn't have dependencies to Git-specific internals unlike in config.[ch]. 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 861e643708..9226c719a0 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 71c84fbcf8..3c0b4fb3d9 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 7dde0aaa02..c7bc21a25d 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" @@ -1165,129 +1166,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; -} - NORETURN static void die_bad_number(const char *name, const char *value, const struct key_value_info *kvi) @@ -1363,23 +1241,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; @@ -1454,16 +1315,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, const struct key_value_info *kvi, int *is_bool) { @@ -2126,35 +1977,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 6332d74904..14f881ecfa 100644 --- a/config.h +++ b/config.h @@ -4,7 +4,7 @@ #include "hashmap.h" #include "string-list.h" #include "repository.h" - +#include "parse.h" /** * The config API gives callers a way to access Git configuration files @@ -243,16 +243,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. @@ -385,8 +375,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 e8e076c3a6..093eaf2db8 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 3a3a5724c4..7f88f1c02b 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 453a20ed99..7da15a56da 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 Fri Sep 8 17:44:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13377752 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 E5144EEB565 for ; Fri, 8 Sep 2023 17:45:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245172AbjIHRpR (ORCPT ); Fri, 8 Sep 2023 13:45:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43024 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245455AbjIHRpH (ORCPT ); Fri, 8 Sep 2023 13:45:07 -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 AE5CC1FEA for ; Fri, 8 Sep 2023 10:44:58 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-5701dbeaf9fso3103925a12.2 for ; Fri, 08 Sep 2023 10:44:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1694195098; x=1694799898; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=cEnG0kNNpgL4K9o3XTg8w1Lw86qqjPuU7AWSct/ZOOU=; b=vhGDOBnMUU3JePi5MiJJu73g0d00oj/HF+NsCKYtGLpDe46/Rd/d6FsP52m6hMo2SB vsKVcwQXXAmee/WnW54CkJNfW/7j7XAFCjLnRJppxKGgnqjVxdLk1BO5T3KhOr2SfWV/ 6NKQCduvbD3R4RZqPMdh1lmlKGJpTEv6szftUFPOQLVgRDFFMZAN+AGbAByEGxH3yipE BmaENIiFs192lS4uN6zg7pfcpYAwBlZgU42WB4P9Oy5AYA4QttZliocMK1yjnLN8tJ2Z Ke2DKzKxDdWRWhy7fx6BrbLJXecoo3tLNckwPKMvqjdEuj1pddZlZcTpkMNmXSsHHbgS i6NA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694195098; x=1694799898; 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=cEnG0kNNpgL4K9o3XTg8w1Lw86qqjPuU7AWSct/ZOOU=; b=DI2RHV2Mbf8poTWWBmylKfU6Ui0kipPQtiGyznoHUuRwrDf9dv8Ljc3xt7LQAvtn/x bZjvOxYfIqbSc5wHwN+KpHx3u0tCBAmCVRGz8ssVS4yq3RsYiwkiN2ZngXlD4YE6lWOW KOogk448USi//o6WJ3N9jR+n1gPbfruNze0qW0I2nbOGK4nMEe0MuPhC5zS9aDIClHr3 TECm37zcfl2pdSMNEJZcDWUAj+a3uRH2tajZFQUEIshRStdqjTZCMmSj2Qr7aPbv9LHH RrJkLrVH1UCaYZV+3m0y6xiPZFoBMLygo5m6g7Gxr+AE11cpyx1mN12DH4GyDS5AZAng lzqQ== X-Gm-Message-State: AOJu0YxhIr76sHU+2vbrsTsoG0L34QiJhAqAIj4o1DZ4AmG8e9e4o5rW nf5SOvjMD4a+9DKj/Sr5PrM74uHMK6TVD24zYx/J23xjleHN5l0tdnTQesbW/+fTdLiWCFYbDfL nJdHgkypf8B1e1HbUfa4gzIWvsDyWGKX3gLz/PKZ5ebbvCf5MxozXBWUHVBF3n912tQ== X-Google-Smtp-Source: AGHT+IHYohkaaPNiRRoqv4xDizlpYoz0FRFW4sM8Ssq2DAfML0cTzfs9X4tVSrLHXBJxYuZrvDKAni2pw99kleo= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a63:3542:0:b0:564:8375:d238 with SMTP id c63-20020a633542000000b005648375d238mr580283pga.4.1694195098104; Fri, 08 Sep 2023 10:44:58 -0700 (PDT) Date: Fri, 8 Sep 2023 17:44:42 +0000 In-Reply-To: <20230908174134.1026823-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230908174134.1026823-1-calvinwan@google.com> X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230908174443.1027716-5-calvinwan@google.com> Subject: [PATCH v3 5/6] git-std-lib: introduce git standard library From: Calvin Wan To: git@vger.kernel.org Cc: Calvin Wan , nasamuffin@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 Helped-by: Phillip Wood --- Documentation/technical/git-std-lib.txt | 191 ++++++++++++++++++++++++ Makefile | 39 ++++- git-compat-util.h | 7 +- stubs/pager.c | 6 + stubs/pager.h | 6 + stubs/trace2.c | 27 ++++ symlinks.c | 2 + wrapper.c | 1 - 8 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 Documentation/technical/git-std-lib.txt create mode 100644 stubs/pager.c create mode 100644 stubs/pager.h create mode 100644 stubs/trace2.c diff --git a/Documentation/technical/git-std-lib.txt b/Documentation/technical/git-std-lib.txt new file mode 100644 index 0000000000..397c1da8c8 --- /dev/null +++ b/Documentation/technical/git-std-lib.txt @@ -0,0 +1,191 @@ +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 what's in and what's not in the 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/pager.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 pager 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 +relevant compat/ files + +When these files are compiled together with the following files (or +user-provided files that provide the same functions), they form a +complete library: +stubs/pager.c +stubs/trace2.c + +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 9226c719a0..0a2d1ae3cc 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_TRACE2 +STUB_OBJS += stubs/trace2.o +endif + +ifdef STUB_PAGER +STUB_OBJS += stubs/pager.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 @@ -3668,7 +3696,7 @@ clean: profile-clean coverage-clean cocciclean $(RM) git.res $(RM) $(OBJECTS) $(RM) headless-git.o - $(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) @@ -3849,3 +3877,12 @@ $(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.a GIT_STD_LIB=YesPlease STUB_TRACE2=YesPlease STUB_PAGER=YesPlease` +STD_LIB = git-std-lib.a + +$(STD_LIB): $(LIB_OBJS) $(COMPAT_OBJS) $(STUB_OBJS) + $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ diff --git a/git-compat-util.h b/git-compat-util.h index 3e7a59b5ff..14bf71c530 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -455,8 +455,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 @@ -966,9 +966,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 static inline size_t st_add(size_t a, size_t b) { @@ -1462,14 +1464,17 @@ static inline int is_missing_file_error(int errno_) return (errno_ == ENOENT || errno_ == ENOTDIR); } +#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/pager.c b/stubs/pager.c new file mode 100644 index 0000000000..4f575cada7 --- /dev/null +++ b/stubs/pager.c @@ -0,0 +1,6 @@ +#include "pager.h" + +int pager_in_use(void) +{ + return 0; +} diff --git a/stubs/pager.h b/stubs/pager.h new file mode 100644 index 0000000000..b797910881 --- /dev/null +++ b/stubs/pager.h @@ -0,0 +1,6 @@ +#ifndef PAGER_H +#define PAGER_H + +int pager_in_use(void); + +#endif /* PAGER_H */ diff --git a/stubs/trace2.c b/stubs/trace2.c new file mode 100644 index 0000000000..7d89482228 --- /dev/null +++ b/stubs/trace2.c @@ -0,0 +1,27 @@ +#include "git-compat-util.h" +#include "trace2.h" + +struct child_process { int stub; }; +struct repository { int stub; }; +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, ...) { } +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_counter_add(enum trace2_counter_id cid, uint64_t value) { } +void trace2_collect_process_info(enum trace2_process_info_reason reason) { } 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 diff --git a/wrapper.c b/wrapper.c index 7da15a56da..eeac3741cf 100644 --- a/wrapper.c +++ b/wrapper.c @@ -5,7 +5,6 @@ #include "abspath.h" #include "parse.h" #include "gettext.h" -#include "repository.h" #include "strbuf.h" #include "trace2.h" From patchwork Fri Sep 8 17:44:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Wan X-Patchwork-Id: 13377753 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 80BEBEEB564 for ; Fri, 8 Sep 2023 17:45:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245442AbjIHRpS (ORCPT ); Fri, 8 Sep 2023 13:45:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245456AbjIHRpH (ORCPT ); Fri, 8 Sep 2023 13:45:07 -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 048DB1FED for ; Fri, 8 Sep 2023 10:45:00 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-570a1c83727so2901706a12.1 for ; Fri, 08 Sep 2023 10:44:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1694195099; x=1694799899; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=AlgE9zKsjtvmJ/dHu1hhc8Vvyo66qzpPDcl+tF3/7QA=; b=PdX8kfdFYWiouHs2lUruSl1bsHMKZyrdMO9fvAJpIofEhMaABCzxu6mahZI0QzspyB N/aG4ue3pQjiq+FJX6VlfIGi+9zvkCKmdjlXEshUfL2KYATk5FtL3dKW56rA1zziBy48 UkWJFjfDvtSFo19B3QiMe/zu85kwsCHV+zDRgr7PTBwaocCM1AKiB81oC+H6+BuHr1uo fkTrjUjvIAoRZlVOrzXBNy+tDzl6v+OG3dKidHoXHpdNrEcv/Ki9FfuADKOIkFB7m5VK 8jOp5alDiZu0C/klz42bqV+3XKU1LobmKgZwemWCJbA80HYcllI+JObNIAD5fNW+PHkP fIwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694195099; x=1694799899; 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=AlgE9zKsjtvmJ/dHu1hhc8Vvyo66qzpPDcl+tF3/7QA=; b=YPToSM8AOW5T3mmG6+UYNSrf1vrSocMsKMW0xz+fnYjyWa/kKg8kvivSbl4j7Q9HhA cYBMefwEBIS+oJjWCU62bIE/GTI9jksKtOdMdWcISgt4z9VsbXInBJ0s+LD3c5Tfv+MR z7kqgFZuynL2kZtvoCzPqmyiFjhYRFzHVywsOGnm4BdoNrzYf1wIq7/Dhc1EijyShDBt e7AKF2gNVELfRxCUcPCcJlwCIOy2N1uQuhEAWtVFJ4FCdciknoIoYOKcxFb0tK56+cPu EQOHZshHyzW+ff5SMmFpvr+30rd3fZgMGQ6jkBomBkU3U2EOLm1W6LcCaDa+iG9vhV2p MkFA== X-Gm-Message-State: AOJu0YwWdSp6Kv4G1L402ZF3Ezyb3uwGxLITy3zDtzuu02retWxteXAX ab2AkFPpNdelbicOXp/8QT6L0V1Qhvqni/owKtAk6vIBdK9DcFYq8y+aDysKoFzGYJ3DbfDVn8y AePDP0KchND3O58boPlHln5LsvR+WVhaNOBY7HEGQ6V8aa0DbjGBDNbGU6CPsGYWfvQ== X-Google-Smtp-Source: AGHT+IEIBdewHdnBSHofrfsqsogsNLu2J+iiC/UG5dEy91PIn5tcQZujjXpkxzBe7VLxyWGW9mxGSwvEn/w8jfs= X-Received: from barleywine.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3bd4]) (user=calvinwan job=sendgmr) by 2002:a65:6ab5:0:b0:56b:b9b1:34e0 with SMTP id x21-20020a656ab5000000b0056bb9b134e0mr621367pgu.11.1694195099473; Fri, 08 Sep 2023 10:44:59 -0700 (PDT) Date: Fri, 8 Sep 2023 17:44:43 +0000 In-Reply-To: <20230908174134.1026823-1-calvinwan@google.com> Mime-Version: 1.0 References: <20230908174134.1026823-1-calvinwan@google.com> X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230908174443.1027716-6-calvinwan@google.com> Subject: [PATCH v3 6/6] 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, 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 | 231 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 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..76fed9ecbf --- /dev/null +++ b/t/stdlib-test.c @@ -0,0 +1,231 @@ +#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"; + 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_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; +}