From patchwork Fri Aug 9 22:41:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 13759292 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 198DE16B38F for ; Fri, 9 Aug 2024 22:41:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243284; cv=none; b=nIDpXe1DUEdunN4xDfV6iqvBlpPoXmyWxIUw7IokOFVaOLtpvJpWorvEkm2DdH5rT4LIvQPezt8NwMNnHs0al/h79QkUd341hIAjyiW9Lr0/46WEwhy2gqT3mBWOD2bhp20oYX8gBVJr+gN63E6OMq8fJMAtHJOZRyLhFGi8eNc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243284; c=relaxed/simple; bh=NyK2HFDSw7hSaHiWdrtNOZi+sdhha5+Vtfw4lO3XNmQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FMT0vIjUxXkGjd916GNVbkEV80wdzi+/iQEVo6NcJW/1eYqiZy/OWqzuQT3h4CFTcZOhLtUHULnFc2FLSf0Yh8QzX1BCh52OijLX930+goM06MiXFjGSRZg+GWYOPnnlNLs3gH8Vbg5EWiHKGD7Z8ww2o5PaaF/BAAJun1Nlhuc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=bavhOiO0; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bavhOiO0" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-690d5456d8aso59507657b3.2 for ; Fri, 09 Aug 2024 15:41:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1723243281; x=1723848081; 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=cEEKPk8J7w840emeTOWTMjY/RH6begc7iSblOouaMo0=; b=bavhOiO0hl7Bxiedmv8pt50r9iVdSXbjV4d9HEUgNM+ZbbEErRb7X1/BdTCqRHM5uT GuHtbC3Kqmc1gl/GiWQjIjhlMvaDv1YEFZDEBogJdCRQW2+goUQiSQ9RNCgkZaNYE5Vk bPI+yavQNXe3CxrkB0+zK+wwt2QwSkzJGuXp50tvoCm8KEanZtYMft4khbUMd3AZxHFf r4OY3v1FhsqXBt42eN2k6dWnUD89G6nMQEpYiDZFMpOX+MIgQ6V9qyr5hd8gphWZA52w uP+3v+vHWEtaAAyR70wHpNqGtyKxy5XIO+jTIDhomfSPKyPZQkiLRBXSFZZLYrxQlgWN k7nQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723243281; x=1723848081; 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=cEEKPk8J7w840emeTOWTMjY/RH6begc7iSblOouaMo0=; b=nFd1AnEpT1oHLBPEkcIijeu6kvcNUQRYH9mcgVUvoCKhJbL2GBm529m1lozrbC64ig 6JcpDGCd2DOrPSSFDhmOUCMV1RFx9T5Ys7nBvushm7geGgiZr3R2InpvbSG51CXe6+uA S0f/OVSPsT1WgSxCqTaCXdlRCsFdPLQ4Ef755aybQP5tONkDI4Mudx1gvVTZkDCiYFpX Sldngxv0Bd4k3EoWpdf/PJdMeUrwjQxq3gF9fvx2QYy95FkCK8r0ZuLuaxvXgc3GWBkV gAxG+JphLxzvO+rx+hchrPQxhz0JauYp4Qseh3IPJuO2vU+QLx6no3wYGW4cU3bHxmS2 o/Xg== X-Gm-Message-State: AOJu0YwOgZp3KvaBuWlnHD7Q5a0qSYIpD6zVSabQOui9DaDC/DHNjgVC RGeoQJH49Auj0GnuuJUgiw3MnqWL25KEm7pCHVv0WuGqqAgYb3lPbpdH8eexp12IVgigZDgExtp ggON+z/scWso6CoIQbZHtP/qsBESNlE0EQm2xzPQslEh+X2wZ1moGtn3bpNMwy3Q317osYOw/E7 CjIKJRERu7yQKwXQgWyygQ/lSsg5C8jmKvnJHdC4w= X-Google-Smtp-Source: AGHT+IHe+2IUiXac8AmcF8m/R5leNskKaIaOn51u77oxr67P2kUuP/GBsP5u1SUYVB/DTl9xkPknTDW0ofZhfw== X-Received: from lunarfall.svl.corp.google.com ([2620:15c:2d3:204:6126:cc38:1b9:851f]) (user=steadmon job=sendgmr) by 2002:a81:bf4f:0:b0:64b:5dc3:e4fe with SMTP id 00721157ae682-69ec492390amr1094157b3.1.1723243280810; Fri, 09 Aug 2024 15:41:20 -0700 (PDT) Date: Fri, 9 Aug 2024 15:41:13 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog Message-ID: <800b37d16b8324faed8b7f84d30f797fc5664bf7.1723242556.git.steadmon@google.com> Subject: [PATCH v2 1/5] common-main: split init and exit code into new files From: Josh Steadmon To: git@vger.kernel.org Cc: calvinwan@google.com, spectral@google.com, emilyshaffer@google.com, emrass@google.com, rsbecker@nexbridge.com, gitster@pobox.com, mh@glandium.org, sandals@crustytoothpaste.net, Jason@zx2c4.com, dsimic@manjaro.org Currently, object files in libgit.a reference common_exit(), which is contained in common-main.o. However, common-main.o also includes main(), which references cmd_main() in git.o, which in turn depends on all the builtin/*.o objects. We would like to allow external users to link libgit.a without needing to include so many extra objects. Enable this by splitting common_exit() and check_bug_if_BUG() into a new file common-exit.c, and add common-exit.o to LIB_OBJS so that these are included in libgit.a. This split has previously been proposed ([1], [2]) to support fuzz tests and unit tests by avoiding conflicting definitions for main(). However, both of those issues were resolved by other methods of avoiding symbol conflicts. Now we are trying to make libgit.a more self-contained, so hopefully we can revisit this approach. Additionally, move the initialization code out of main() into a new init_git() function in its own file. Include this in libgit.a as well, so that external users can share our setup code without calling our main(). [1] https://lore.kernel.org/git/Yp+wjCPhqieTku3X@google.com/ [2] https://lore.kernel.org/git/20230517-unit-tests-v2-v2-1-21b5b60f4b32@google.com/ Signed-off-by: Josh Steadmon --- Makefile | 2 ++ common-exit.c | 26 ++++++++++++++++ common-init.c | 63 ++++++++++++++++++++++++++++++++++++++ common-init.h | 6 ++++ common-main.c | 83 ++------------------------------------------------- 5 files changed, 99 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h diff --git a/Makefile b/Makefile index 3eab701b10..7caeb3c872 100644 --- a/Makefile +++ b/Makefile @@ -979,6 +979,8 @@ LIB_OBJS += combine-diff.o LIB_OBJS += commit-graph.o LIB_OBJS += commit-reach.o LIB_OBJS += commit.o +LIB_OBJS += common-exit.o +LIB_OBJS += common-init.o LIB_OBJS += compat/nonblock.o LIB_OBJS += compat/obstack.o LIB_OBJS += compat/terminal.o diff --git a/common-exit.c b/common-exit.c new file mode 100644 index 0000000000..1aaa538be3 --- /dev/null +++ b/common-exit.c @@ -0,0 +1,26 @@ +#include "git-compat-util.h" +#include "trace2.h" + +static void check_bug_if_BUG(void) +{ + if (!bug_called_must_BUG) + return; + BUG("on exit(): had bug() call(s) in this process without explicit BUG_if_bug()"); +} + +/* We wrap exit() to call common_exit() in git-compat-util.h */ +int common_exit(const char *file, int line, int code) +{ + /* + * For non-POSIX systems: Take the lowest 8 bits of the "code" + * to e.g. turn -1 into 255. On a POSIX system this is + * redundant, see exit(3) and wait(2), but as it doesn't harm + * anything there we don't need to guard this with an "ifdef". + */ + code &= 0xff; + + check_bug_if_BUG(); + trace2_cmd_exit_fl(file, line, code); + + return code; +} diff --git a/common-init.c b/common-init.c new file mode 100644 index 0000000000..5cc73f058c --- /dev/null +++ b/common-init.c @@ -0,0 +1,63 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "git-compat-util.h" +#include "common-init.h" +#include "exec-cmd.h" +#include "gettext.h" +#include "attr.h" +#include "repository.h" +#include "setup.h" +#include "strbuf.h" +#include "trace2.h" + +/* + * Many parts of Git have subprograms communicate via pipe, expect the + * upstream of a pipe to die with SIGPIPE when the downstream of a + * pipe does not need to read all that is written. Some third-party + * programs that ignore or block SIGPIPE for their own reason forget + * to restore SIGPIPE handling to the default before spawning Git and + * break this carefully orchestrated machinery. + * + * Restore the way SIGPIPE is handled to default, which is what we + * expect. + */ +static void restore_sigpipe_to_default(void) +{ + sigset_t unblock; + + sigemptyset(&unblock); + sigaddset(&unblock, SIGPIPE); + sigprocmask(SIG_UNBLOCK, &unblock, NULL); + signal(SIGPIPE, SIG_DFL); +} + +void init_git(const char **argv) +{ + struct strbuf tmp = STRBUF_INIT; + + trace2_initialize_clock(); + + /* + * Always open file descriptors 0/1/2 to avoid clobbering files + * in die(). It also avoids messing up when the pipes are dup'ed + * onto stdin/stdout/stderr in the child processes we spawn. + */ + sanitize_stdfds(); + restore_sigpipe_to_default(); + + git_resolve_executable_dir(argv[0]); + + setlocale(LC_CTYPE, ""); + git_setup_gettext(); + + initialize_repository(the_repository); + + attr_start(); + + trace2_initialize(); + trace2_cmd_start(argv); + trace2_collect_process_info(TRACE2_PROCESS_INFO_STARTUP); + + if (!strbuf_getcwd(&tmp)) + tmp_original_cwd = strbuf_detach(&tmp, NULL); +} diff --git a/common-init.h b/common-init.h new file mode 100644 index 0000000000..3e6db20cae --- /dev/null +++ b/common-init.h @@ -0,0 +1,6 @@ +#ifndef COMMON_INIT_H +#define COMMON_INIT_H + +void init_git(const char **argv); + +#endif /* COMMON_INIT_H */ diff --git a/common-main.c b/common-main.c index 8e68ac9e42..6b7ab077b0 100644 --- a/common-main.c +++ b/common-main.c @@ -1,92 +1,13 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" -#include "exec-cmd.h" -#include "gettext.h" -#include "attr.h" -#include "repository.h" -#include "setup.h" -#include "strbuf.h" -#include "trace2.h" - -/* - * Many parts of Git have subprograms communicate via pipe, expect the - * upstream of a pipe to die with SIGPIPE when the downstream of a - * pipe does not need to read all that is written. Some third-party - * programs that ignore or block SIGPIPE for their own reason forget - * to restore SIGPIPE handling to the default before spawning Git and - * break this carefully orchestrated machinery. - * - * Restore the way SIGPIPE is handled to default, which is what we - * expect. - */ -static void restore_sigpipe_to_default(void) -{ - sigset_t unblock; - - sigemptyset(&unblock); - sigaddset(&unblock, SIGPIPE); - sigprocmask(SIG_UNBLOCK, &unblock, NULL); - signal(SIGPIPE, SIG_DFL); -} +#include "common-init.h" int main(int argc, const char **argv) { int result; - struct strbuf tmp = STRBUF_INIT; - - trace2_initialize_clock(); - - /* - * Always open file descriptors 0/1/2 to avoid clobbering files - * in die(). It also avoids messing up when the pipes are dup'ed - * onto stdin/stdout/stderr in the child processes we spawn. - */ - sanitize_stdfds(); - restore_sigpipe_to_default(); - - git_resolve_executable_dir(argv[0]); - - setlocale(LC_CTYPE, ""); - git_setup_gettext(); - - initialize_repository(the_repository); - - attr_start(); - - trace2_initialize(); - trace2_cmd_start(argv); - trace2_collect_process_info(TRACE2_PROCESS_INFO_STARTUP); - - if (!strbuf_getcwd(&tmp)) - tmp_original_cwd = strbuf_detach(&tmp, NULL); + init_git(argv); result = cmd_main(argc, argv); /* Not exit(3), but a wrapper calling our common_exit() */ exit(result); } - -static void check_bug_if_BUG(void) -{ - if (!bug_called_must_BUG) - return; - BUG("on exit(): had bug() call(s) in this process without explicit BUG_if_bug()"); -} - -/* We wrap exit() to call common_exit() in git-compat-util.h */ -int common_exit(const char *file, int line, int code) -{ - /* - * For non-POSIX systems: Take the lowest 8 bits of the "code" - * to e.g. turn -1 into 255. On a POSIX system this is - * redundant, see exit(3) and wait(2), but as it doesn't harm - * anything there we don't need to guard this with an "ifdef". - */ - code &= 0xff; - - check_bug_if_BUG(); - trace2_cmd_exit_fl(file, line, code); - - return code; -} From patchwork Fri Aug 9 22:41:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 13759293 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 516BE16B736 for ; Fri, 9 Aug 2024 22:41:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243286; cv=none; b=lFb6mVy15yhpiZa+ChCpE265iODRH1xZsDhokDOf0brt8kATkPVt6L8oloK8RWSPoXOa6+jVvTPONJSFNhhoMQb0p7hHlRQnHcVU0MiS5bvVV+W0no9Lbgc+PeaWbq1UKpteVxYhKtaEH2a7fQ9HEHSz1o8fmk5PtQieNsiE/w4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243286; c=relaxed/simple; bh=P9SN01TY9qrYrAXutS0gKDc9Y2uf/Kgt2pipebGiooY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=r6w/g1EmmXjjhDYcfkElBVWtOaUO/n/Je7zYHTj5zCJHuzvep0syD/2jnsU2UmqUnigPZ/bE0tWy6CnO2UFXwuZD1xrXwNvzU6yCzdnGixjsg+YkPrhnF9jqi8nl9jhk7+s9KrlD6n09hDeEb9Sudkbg3qVxPTlkcKdYZozLtag= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Lbwmww9Q; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Lbwmww9Q" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6698f11853aso50534177b3.0 for ; Fri, 09 Aug 2024 15:41:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1723243283; x=1723848083; 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=fDAipBjx3OBFPucxd82g5x3Ir4onD690hU+TZ6kUsxM=; b=Lbwmww9QMAxPnQlNQi/OZ7EvgOeFeeZYfoKrF76PAK3lJHzJYc3Jy1ZUSOrd4vfSRt SqJElS3dcgiOPsjCPP8FxSIKFGOEk3pge92+MXIt1D5CvkR58yItTyF4qC9BDBnGykwR 0VOu8QvopPVU5nRWJRPmpQGlDwN1S5oPTVGNUV8s1v0fnrEvuQBXaY0xXv+0xvjZQ5uq wbMLyGpaA8ZDuUgCU8wIVJ4eV/pYChdscmtc/NwrsLIWrXeUiq6oyUoCX3/i5IeeMefB HIBJkJkxLIeR9D+is45GP/NkEDyuV+rOSB5ttc/F6iuEExdizUAbzRnqUDsEUPtenhen qAPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723243283; x=1723848083; 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=fDAipBjx3OBFPucxd82g5x3Ir4onD690hU+TZ6kUsxM=; b=L6sxOse/VbDs0KoCme6AlFC50+RGZJKThamEQvt05PpFtvXr25lxjfNbnJjMIu99ne Jf+PHPLzzEqS2usWgTR3rYLSQRooh0yznEXeqlxa4UzDbA/OtHCfAYfNZ4Tyznmwsszl +LhNgIgoNBSav6PxPwDvdNfRMI1KJPjg2SfH+Q8YjcIffUR8uBJrlymIso2HP/jva4Iu YRsKKJMZ6nnqZo9mVIr931gcfPf02Yb+FjDYOQtH1S4iQ202e33Oc9E+jD3h2zDfOFhE HU4ZC4/j2tTFz/ZfhK7aN9WRDT88yOfO11u0tLVR6WWc08OATGDf90uvdi3RRPt2OsFa Sclg== X-Gm-Message-State: AOJu0YyF2qEa+PyO621aQnEMnJP0BsL1JBpEvZlUWWoDl+Na5poz8Zwj SPHU8wgy8egobvD/PcNQUf47avWAb4iPvT38wTHpyuxmP2LR3z2HEkbA8cZmobpluiuYsDhCqhU SoYgnD8v4yrUwvlU5x+aEsDUzI+gq7oLIQBeERI2Mns6FtjgJccABjnTTqE+Y+MOTfU7Jgnru4l rDKU1L9GRJef/P/22NJkTWqX+pFPemltdsVRCM28k= X-Google-Smtp-Source: AGHT+IGU4g3AO90ajuNfTJhpKFXQPH8eO4xDqfbTU9SpJCI17s93qWAYq1odI5jN8PQwlRiMG5MK6u4DftuRpA== X-Received: from lunarfall.svl.corp.google.com ([2620:15c:2d3:204:6126:cc38:1b9:851f]) (user=steadmon job=sendgmr) by 2002:a5b:d44:0:b0:e0e:426b:bf6f with SMTP id 3f1490d57ef6-e0eb99f2ea1mr6167276.7.1723243282469; Fri, 09 Aug 2024 15:41:22 -0700 (PDT) Date: Fri, 9 Aug 2024 15:41:14 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog Message-ID: <3589d2d6a2a24c2cc558d8e8fd05b56e28627eae.1723242556.git.steadmon@google.com> Subject: [PATCH v2 2/5] cgit-sys: introduce Rust wrapper for libgit.a From: Josh Steadmon To: git@vger.kernel.org Cc: calvinwan@google.com, spectral@google.com, emilyshaffer@google.com, emrass@google.com, rsbecker@nexbridge.com, gitster@pobox.com, mh@glandium.org, sandals@crustytoothpaste.net, Jason@zx2c4.com, dsimic@manjaro.org Introduce cgit-sys, a Rust wrapper crate that allows Rust code to call functions in libgit.a. This initial patch defines build rules and an interface that exposes user agent string getter functions as a proof of concept. This library can be tested with `cargo test`. In later commits, a higher-level library providing a more Rust-friendly interface will be added at `contrib/cgit-rs`. Symbols in cgit-sys can collide with symbols from other libraries such as libgit2. We avoid this by first exposing library symbols in public_symbol_export.[ch]. These symbols are prepended with "libgit_" to avoid collisions and set to visible using a visibility pragma. In build.rs, Rust builds contrib/cgit-rs/cgit-sys/libcgit.a, which also contains libgit.a and other dependent libraries, with -fvisibility=hidden to hide all symbols within those libraries that haven't been exposed with a visibility pragma. Co-authored-by: Kyle Lippincott Co-authored-by: Calvin Wan Co-authored-by: Josh Steadmon Signed-off-by: Calvin Wan Signed-off-by: Kyle Lippincott Signed-off-by: Josh Steadmon --- .gitignore | 1 + Makefile | 13 ++++++ contrib/cgit-rs/cgit-sys/Cargo.lock | 7 ++++ contrib/cgit-rs/cgit-sys/Cargo.toml | 9 +++++ contrib/cgit-rs/cgit-sys/README.md | 15 +++++++ contrib/cgit-rs/cgit-sys/build.rs | 32 +++++++++++++++ .../cgit-rs/cgit-sys/public_symbol_export.c | 20 ++++++++++ .../cgit-rs/cgit-sys/public_symbol_export.h | 8 ++++ contrib/cgit-rs/cgit-sys/src/lib.rs | 40 +++++++++++++++++++ 9 files changed, 145 insertions(+) create mode 100644 contrib/cgit-rs/cgit-sys/Cargo.lock create mode 100644 contrib/cgit-rs/cgit-sys/Cargo.toml create mode 100644 contrib/cgit-rs/cgit-sys/README.md create mode 100644 contrib/cgit-rs/cgit-sys/build.rs create mode 100644 contrib/cgit-rs/cgit-sys/public_symbol_export.c create mode 100644 contrib/cgit-rs/cgit-sys/public_symbol_export.h create mode 100644 contrib/cgit-rs/cgit-sys/src/lib.rs diff --git a/.gitignore b/.gitignore index 8caf3700c2..567cc9888f 100644 --- a/.gitignore +++ b/.gitignore @@ -248,3 +248,4 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/cgit-rs/cgit-sys/target diff --git a/Makefile b/Makefile index 7caeb3c872..db8af99f20 100644 --- a/Makefile +++ b/Makefile @@ -653,6 +653,8 @@ CURL_CONFIG = curl-config GCOV = gcov STRIP = strip SPATCH = spatch +LD = ld +OBJCOPY = objcopy export TCL_PATH TCLTK_PATH @@ -2713,6 +2715,7 @@ OBJECTS += $(XDIFF_OBJS) OBJECTS += $(FUZZ_OBJS) OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS) OBJECTS += $(UNIT_TEST_OBJS) +OBJECTS += contrib/cgit-rs/cgit-sys/public_symbol_export.o ifndef NO_CURL OBJECTS += http.o http-walker.o remote-curl.o @@ -3720,6 +3723,7 @@ clean: profile-clean coverage-clean cocciclean $(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(MAKE) -C Documentation/ clean $(RM) Documentation/GIT-EXCLUDED-PROGRAMS + $(RM) -r contrib/cgit-rs/cgit-sys/target ifndef NO_PERL $(RM) -r perl/build/ endif @@ -3865,3 +3869,12 @@ $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \ build-unit-tests: $(UNIT_TEST_PROGS) unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X $(MAKE) -C t/ unit-tests + +contrib/cgit-rs/cgit-sys/partial_symbol_export.o: contrib/cgit-rs/cgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a + $(LD) -r $^ -o $@ + +contrib/cgit-rs/cgit-sys/hidden_symbol_export.o: contrib/cgit-rs/cgit-sys/partial_symbol_export.o + $(OBJCOPY) --localize-hidden $^ $@ + +contrib/cgit-rs/cgit-sys/libcgit.a: contrib/cgit-rs/cgit-sys/hidden_symbol_export.o + $(AR) $(ARFLAGS) $@ $^ diff --git a/contrib/cgit-rs/cgit-sys/Cargo.lock b/contrib/cgit-rs/cgit-sys/Cargo.lock new file mode 100644 index 0000000000..419a6d42f2 --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cgit-sys" +version = "0.1.0" diff --git a/contrib/cgit-rs/cgit-sys/Cargo.toml b/contrib/cgit-rs/cgit-sys/Cargo.toml new file mode 100644 index 0000000000..e840f04024 --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "cgit-sys" +version = "0.1.0" +edition = "2021" +build = "build.rs" +links = "git" + +[lib] +path = "src/lib.rs" diff --git a/contrib/cgit-rs/cgit-sys/README.md b/contrib/cgit-rs/cgit-sys/README.md new file mode 100644 index 0000000000..7a59602c30 --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/README.md @@ -0,0 +1,15 @@ +# cgit-info + +A small hacky proof-of-concept showing how to provide a Rust FFI for the Git +library. + +## Building + +`cargo build` automatically builds and picks up on changes made to both +the Rust wrapper and git.git code so there is no need to run `make` +beforehand. + +## Running + +Assuming you don't make any changes to the Git source, you can just work from +`contrib/cgit-rs` and use `cargo build` or `cargo run` as usual. diff --git a/contrib/cgit-rs/cgit-sys/build.rs b/contrib/cgit-rs/cgit-sys/build.rs new file mode 100644 index 0000000000..e29d703870 --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/build.rs @@ -0,0 +1,32 @@ +use std::env; +use std::path::PathBuf; + +pub fn main() -> std::io::Result<()> { + let crate_root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let git_root = crate_root.join("../../.."); + let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + let make_output = std::process::Command::new("make") + .env_remove("PROFILE") + .current_dir(git_root.clone()) + .args([ + "CFLAGS=-fvisibility=hidden", + "contrib/cgit-rs/cgit-sys/libcgit.a", + ]) + .output() + .expect("Make failed to run"); + if !make_output.status.success() { + panic!( + "Make failed:\n stdout = {}\n stderr = {}\n", + String::from_utf8(make_output.stdout).unwrap(), + String::from_utf8(make_output.stderr).unwrap() + ); + } + std::fs::copy(crate_root.join("libcgit.a"), dst.join("libcgit.a"))?; + println!("cargo::rustc-link-search=native={}", dst.display()); + println!("cargo::rustc-link-lib=cgit"); + println!("cargo::rustc-link-lib=z"); + println!("cargo::rerun-if-changed={}", git_root.display()); + + Ok(()) +} diff --git a/contrib/cgit-rs/cgit-sys/public_symbol_export.c b/contrib/cgit-rs/cgit-sys/public_symbol_export.c new file mode 100644 index 0000000000..deef4488c0 --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/public_symbol_export.c @@ -0,0 +1,20 @@ +// Shim to publicly export Git symbols. These must be renamed so that the +// original symbols can be hidden. Renaming these with a "libgit_" prefix also +// avoid conflicts with other libraries such as libgit2. + +#include "contrib/cgit-rs/cgit-sys/public_symbol_export.h" +#include "version.h" + +#pragma GCC visibility push(default) + +const char *libgit_user_agent(void) +{ + return git_user_agent(); +} + +const char *libgit_user_agent_sanitized(void) +{ + return git_user_agent_sanitized(); +} + +#pragma GCC visibility pop diff --git a/contrib/cgit-rs/cgit-sys/public_symbol_export.h b/contrib/cgit-rs/cgit-sys/public_symbol_export.h new file mode 100644 index 0000000000..a3372f93fa --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/public_symbol_export.h @@ -0,0 +1,8 @@ +#ifndef PUBLIC_SYMBOL_EXPORT_H +#define PUBLIC_SYMBOL_EXPORT_H + +const char *libgit_user_agent(void); + +const char *libgit_user_agent_sanitized(void); + +#endif /* PUBLIC_SYMBOL_EXPORT_H */ diff --git a/contrib/cgit-rs/cgit-sys/src/lib.rs b/contrib/cgit-rs/cgit-sys/src/lib.rs new file mode 100644 index 0000000000..bc33c6c498 --- /dev/null +++ b/contrib/cgit-rs/cgit-sys/src/lib.rs @@ -0,0 +1,40 @@ +use std::ffi::c_char; + +extern "C" { + // From version.c + pub fn libgit_user_agent() -> *const c_char; + pub fn libgit_user_agent_sanitized() -> *const c_char; +} + +#[cfg(test)] +mod tests { + use std::ffi::CStr; + + use super::*; + + #[test] + fn user_agent_starts_with_git() { + let c_str = unsafe { CStr::from_ptr(libgit_user_agent()) }; + let agent = c_str + .to_str() + .expect("User agent contains invalid UTF-8 data"); + assert!( + agent.starts_with("git/"), + r#"Expected user agent to start with "git/", got: {}"#, + agent + ); + } + + #[test] + fn sanitized_user_agent_starts_with_git() { + let c_str = unsafe { CStr::from_ptr(libgit_user_agent_sanitized()) }; + let agent = c_str + .to_str() + .expect("Sanitized user agent contains invalid UTF-8 data"); + assert!( + agent.starts_with("git/"), + r#"Expected user agent to start with "git/", got: {}"#, + agent + ); + } +} From patchwork Fri Aug 9 22:41:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 13759294 Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3013516CD06 for ; Fri, 9 Aug 2024 22:41:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243287; cv=none; b=Ywlc7wBV+l6Sq0SoCLsU2WFmixlCrq5fnhKNcJJpytf9q0MyEot1VmWZEffJOrVua7PO8A9vEI6SuGpIYy8I7R4EJfXw+9eNq5elii96LVDlG9GxkFXyz1ANWD2Lb0a74ON4HbyVs4t6qqeHmpkHjnUztbSdkguwEpyRAXBFAbs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243287; c=relaxed/simple; bh=jIrYBlVw3WJyfjdFlZgC7v0CIMcxDLQpL/rCED5y1fY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Raaew6YCyP1IrTWTIs3qp5SS4y0dPqhEpsyRgTjibBIeJNeiQDLUks0qGGXqO7b5TfnkKylq8z87W3rlvo6wBF3C4MqPyJISSTLd/73UFH6OFpRzr/dak3e9j2icP2W1Nt8SLCWmZS+YIMEk+RT7GE3Qu+tS1+h0uCum9MRptp4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=3+BeeS04; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="3+BeeS04" Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-e0ba4d19585so4319863276.0 for ; Fri, 09 Aug 2024 15:41:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1723243285; x=1723848085; 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=rzmHUEhogeMZwKfl63adstzyZtv39oYc2/8qG5tnYh4=; b=3+BeeS043zmDBzAlXax3qsBsS+sfbB5E6LBcjo6plzuqtO118DmrZp5btQ+HlB2ZIL B+wUq5ujhWiJxqQuS6kZxkItwPdu/r/3TZ3tSCXf+sTDiaGPudlP8XGUeqav6AnXEHYu s1oovaWH2zOL2GXNJPMWF+NSruKsvm7bSl2sPWVm77XSazRxmHJgVAccfzQZHHD5qV2g dVfnZyzp1Yna0yibOCx5K/QCXxZWugN+89eXI+pTJVgTyxO/06Rl6JJINE6DEBCW1H5G VfoyyXDv8WSx3+muJXXwwjKQ/WUYzI+vZpUUcrJaj0ejy7ldBxgFR+cW7jOeWOhjuIzM OV/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723243285; x=1723848085; 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=rzmHUEhogeMZwKfl63adstzyZtv39oYc2/8qG5tnYh4=; b=B0zXyIF46zYwAHSLlXAG88jynTircFTWB5Jg4yZ3o1+p+NsyJKIOJrhreydJMPO96Y C2Uqc9DDyE54sw/HStx4K0PLOTbPdHwfoK9SfyP66KK+5Bk9/7bKR75LpamDiVtCGYDX lFWb0dmyj8mQ4zg2r0e1DtzeUqjEv77O1QaVos9tb27dyp/XbPuse4o18IbH5mCBW8Vb UU4GvLBzWVnZp+6B3vxVnflLzhGa/Vi7GPnFwuBEaKCVrR4oLalXnlmcZ/1PWbmvnth0 6O507xu8p2PR2lqKjcixRVDAsst4Z3FcD3MkEW689kzaEvdgjt+rnWzjvig8QWAyJMA1 v21g== X-Gm-Message-State: AOJu0YxwLKacHs8Y+sBvZIx28p5BceeIOPgHXs+fKlAklocJRzvRtet1 dAJzFfT8kMdKsqu7Yz/FbytNQC53Pp+WDHSe83PjJwwbEkHoXfco2VQnpQA0/r4/Sygi5KwNHX6 bWkDdu+IW7LitqZo2ZpH8TCYKonQyHXvYS8/lVX6UqBOFQIpbKMpwbspmC8+YArbeRqFo4xQBi3 mMZk3spa5diOoLt/A55nm84MmQBnHn5wL8TW10ERg= X-Google-Smtp-Source: AGHT+IHqCdMEu+jEnHfAYAF1bWkPHKCSJ/gdUeUwEJYrBxrWhJJt/XhLSsbTtAJxSFCgAzPyQawbtJUKdZaNhw== X-Received: from lunarfall.svl.corp.google.com ([2620:15c:2d3:204:6126:cc38:1b9:851f]) (user=steadmon job=sendgmr) by 2002:a25:69cd:0:b0:e03:2f8e:9d81 with SMTP id 3f1490d57ef6-e0eb9790248mr6592276.0.1723243284399; Fri, 09 Aug 2024 15:41:24 -0700 (PDT) Date: Fri, 9 Aug 2024 15:41:15 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog Message-ID: <527780f816028f4c60db8f51ce06de090cb51286.1723242556.git.steadmon@google.com> Subject: [PATCH v2 3/5] cgit-sys: add repo initialization and config access From: Josh Steadmon To: git@vger.kernel.org Cc: calvinwan@google.com, spectral@google.com, emilyshaffer@google.com, emrass@google.com, rsbecker@nexbridge.com, gitster@pobox.com, mh@glandium.org, sandals@crustytoothpaste.net, Jason@zx2c4.com, dsimic@manjaro.org From: Calvin Wan Wrap a few repo setup and config access functions in cgit-sys. These were selected as proof-of-concept items to show that we can access local config from Rust. Co-authored-by: Josh Steadmon Signed-off-by: Calvin Wan Signed-off-by: Josh Steadmon --- .../cgit-rs/cgit-sys/public_symbol_export.c | 26 ++++++++++ .../cgit-rs/cgit-sys/public_symbol_export.h | 8 ++++ contrib/cgit-rs/cgit-sys/src/lib.rs | 47 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/contrib/cgit-rs/cgit-sys/public_symbol_export.c b/contrib/cgit-rs/cgit-sys/public_symbol_export.c index deef4488c0..62a91f76d0 100644 --- a/contrib/cgit-rs/cgit-sys/public_symbol_export.c +++ b/contrib/cgit-rs/cgit-sys/public_symbol_export.c @@ -2,11 +2,37 @@ // original symbols can be hidden. Renaming these with a "libgit_" prefix also // avoid conflicts with other libraries such as libgit2. +#include "git-compat-util.h" #include "contrib/cgit-rs/cgit-sys/public_symbol_export.h" +#include "common-init.h" +#include "config.h" +#include "setup.h" #include "version.h" +extern struct repository *the_repository; + #pragma GCC visibility push(default) +const char *libgit_setup_git_directory(void) +{ + return setup_git_directory(); +} + +int libgit_config_get_int(const char *key, int *dest) +{ + return repo_config_get_int(the_repository, key, dest); +} + +void libgit_init_git(const char **argv) +{ + init_git(argv); +} + +int libgit_parse_maybe_bool(const char *val) +{ + return git_parse_maybe_bool(val); +} + const char *libgit_user_agent(void) { return git_user_agent(); diff --git a/contrib/cgit-rs/cgit-sys/public_symbol_export.h b/contrib/cgit-rs/cgit-sys/public_symbol_export.h index a3372f93fa..64332f30de 100644 --- a/contrib/cgit-rs/cgit-sys/public_symbol_export.h +++ b/contrib/cgit-rs/cgit-sys/public_symbol_export.h @@ -1,6 +1,14 @@ #ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +const char *libgit_setup_git_directory(void); + +int libgit_config_get_int(const char *key, int *dest); + +void libgit_init_git(const char **argv); + +int libgit_parse_maybe_bool(const char *val); + const char *libgit_user_agent(void); const char *libgit_user_agent_sanitized(void); diff --git a/contrib/cgit-rs/cgit-sys/src/lib.rs b/contrib/cgit-rs/cgit-sys/src/lib.rs index bc33c6c498..8c3ccc2859 100644 --- a/contrib/cgit-rs/cgit-sys/src/lib.rs +++ b/contrib/cgit-rs/cgit-sys/src/lib.rs @@ -1,6 +1,17 @@ -use std::ffi::c_char; +use std::ffi::{c_char, c_int}; extern "C" { + pub fn libgit_setup_git_directory() -> *const c_char; + + // From config.c + pub fn libgit_config_get_int(key: *const c_char, dest: *mut c_int) -> c_int; + + // From common-init.c + pub fn libgit_init_git(argv: *const *const c_char); + + // From parse.c + pub fn libgit_parse_maybe_bool(val: *const c_char) -> c_int; + // From version.c pub fn libgit_user_agent() -> *const c_char; pub fn libgit_user_agent_sanitized() -> *const c_char; @@ -8,7 +19,7 @@ extern "C" { #[cfg(test)] mod tests { - use std::ffi::CStr; + use std::ffi::{CStr, CString}; use super::*; @@ -37,4 +48,36 @@ mod tests { agent ); } + + #[test] + fn parse_bools_from_strings() { + let arg = CString::new("true").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 1); + + let arg = CString::new("yes").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 1); + + let arg = CString::new("false").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 0); + + let arg = CString::new("no").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 0); + + let arg = CString::new("maybe").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, -1); + } + + #[test] + fn access_configs() { + // NEEDSWORK: we need to supply a testdata config + let fake_argv = [std::ptr::null::()]; + unsafe { + libgit_init_git(fake_argv.as_ptr()); + libgit_setup_git_directory(); + } + let mut val: c_int = 0; + let key = CString::new("trace2.eventNesting").unwrap(); + unsafe { libgit_config_get_int(key.as_ptr(), &mut val as *mut i32) }; + assert_eq!(val, 5); + } } From patchwork Fri Aug 9 22:41:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 13759295 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 904A816D315 for ; Fri, 9 Aug 2024 22:41:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243289; cv=none; b=t0rwWyOPA0TLyMEjceKKmRJ3gcA4eRP6BnVJBy/p3fdUlXl04ZDgivofBdPFle3TTPFhwSkPjXAK8D7WZ6Dl6W/K3ZvXKxqKGSAn8Oey6qjeRhNkhN1Qhf5wh50uXkNvx8DQLe4ojCe1rCSlDV1XlKH9OjitZeJjphEaBKigG14= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243289; c=relaxed/simple; bh=XGxIh6o4z04vy8A/yAcaN2qeQppZedVs0LMviRQ6sjI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=BTegwrnzubqJn9Rpa0dnICLtp4DZafcnxUSBnMmDAyz002Z8VJ/2h4BGVlxo1yBidAhjAdm8+x4tzD4r/lO/wLwkLtOX0/Rt3e+7itpBxN4FMmwef3tV5HLow+1X4xG+ZaxUN6W2MWDtX7AWNozfrkWQZV1rSo8dGHWTFT29uAg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=EY9FIY95; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="EY9FIY95" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-664fc7c4e51so52333527b3.3 for ; Fri, 09 Aug 2024 15:41:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1723243286; x=1723848086; 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=8O8L58z+pSeLkSMIC8NopkCyxoaH0uGAl+ihme5B/TE=; b=EY9FIY95zVmY1rzQIWQumPj/AVt//R2yGYHA0LKWb4k2doRURN+o+y5wpRC4K11d4l wzHvCewoO0TdyixjuKslFuWCObWwfwjyvvNc1NVwnycQlWTU939qUga5lIBXsd/7byfe akpm+VIHOh5gonIgNuBV3C67NRHA0YcvnzZ4akE8yDcEuLEVyxIlJYkMQy+TdiOTjjIL 5mx63rXjvxfP/GK4VsLTKs5LZNy3PaVZY8Nl44D0+GtdowZjpWzEETVvm7c3y99Uh6Cc S7vbx1e3zFS9NbLacdsaHA7o/gLYGPiWq5SOyJreHzcgHV+motxEpkg5+vWYlxJhqVy/ hVOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723243286; x=1723848086; 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=8O8L58z+pSeLkSMIC8NopkCyxoaH0uGAl+ihme5B/TE=; b=tCflAu4lLUjYRZ75ZLDMjnhdYeaSoifPI+RjXuj1MtsqMzWKdoD+PrUOmg6CIG5M/u U4WXjvldAkbtT2mV6BVX4Tzi+PAR+zjcgFst0STBpeve53Kt2eOrsmAbt74ZbfDjYa8X WJIrPb7nBHN9kpYW8PL6gHLGLaeDHooRQgE9O0F3R/OV3xzZ5XVAaL4ys2nuunstm5JG Du6tcVUJBg98I4ZpPXDcCfw9DN4zkfG1wuicDw/t83ARYcQttow269Wu3etbWgT5hJh8 H0c4M0+GEBsSiBU31GAqrHhP3lIaEmxcpajTVaI+JDiLdvJOiPy8ilCRAezF21RTq4gJ +y0w== X-Gm-Message-State: AOJu0Yy7cWa6aU/8mSiofqXofhxtnkeyHa/4qs0XGbBcc/tBploU3Qcd q/dAn6wTaPLmdzdVOrO9+5ntuIHeBGoWZu/qMe3IYCyUvWxNpHb6ZNwqe9Ug8nk5X5X+7XRgx8b s3PPwJAeHbTb+Bfb87bzYKuwB0sUunOBftpKOuxL+W5H+uWglrluH03bhHUV+6UPHVyNL02r/zy 97e/Mtr6sWnjT8Suj0Ll1g/Y0WOZaFI+PWY5OyNMU= X-Google-Smtp-Source: AGHT+IH9ekYqX187NH/F6VdoKV3ctmF3bsf8FkK/HHKWuEYiv17mU45M3bSYproWAyxPCQohw58BkMqZqmM+Mg== X-Received: from lunarfall.svl.corp.google.com ([2620:15c:2d3:204:6126:cc38:1b9:851f]) (user=steadmon job=sendgmr) by 2002:a05:690c:2f81:b0:68f:dfc2:98ee with SMTP id 00721157ae682-69ec86c66e2mr224507b3.5.1723243286254; Fri, 09 Aug 2024 15:41:26 -0700 (PDT) Date: Fri, 9 Aug 2024 15:41:16 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog Message-ID: <908ad0b82fa084fc4e56d7f6dff49e4f255af6ec.1723242556.git.steadmon@google.com> Subject: [PATCH v2 4/5] config: add git_configset_alloc() and git_configset_clear_and_free() From: Josh Steadmon To: git@vger.kernel.org Cc: calvinwan@google.com, spectral@google.com, emilyshaffer@google.com, emrass@google.com, rsbecker@nexbridge.com, gitster@pobox.com, mh@glandium.org, sandals@crustytoothpaste.net, Jason@zx2c4.com, dsimic@manjaro.org Add git_configset_alloc() and git_configset_clear_and_free() functions so that callers can manage config_set structs on the heap. This also allows non-C external consumers to treat config_sets as opaque structs. Co-authored-by: Calvin Wan Signed-off-by: Calvin Wan Signed-off-by: Josh Steadmon --- config.c | 11 +++++++++++ config.h | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/config.c b/config.c index 6421894614..444db8de79 100644 --- a/config.c +++ b/config.c @@ -2324,6 +2324,11 @@ static int config_set_element_cmp(const void *cmp_data UNUSED, return strcmp(e1->key, e2->key); } +struct config_set *git_configset_alloc(void) +{ + return xmalloc(sizeof(struct config_set)); +} + void git_configset_init(struct config_set *set) { hashmap_init(&set->config_hash, config_set_element_cmp, NULL, 0); @@ -2353,6 +2358,12 @@ void git_configset_clear(struct config_set *set) set->list.items = NULL; } +void git_configset_clear_and_free(struct config_set *set) +{ + git_configset_clear(set); + free(set); +} + static int config_set_callback(const char *key, const char *value, const struct config_context *ctx, void *cb) diff --git a/config.h b/config.h index 54b47dec9e..074c85a788 100644 --- a/config.h +++ b/config.h @@ -472,6 +472,11 @@ struct config_set { struct configset_list list; }; +/** + * Alloc a config_set + */ +struct config_set *git_configset_alloc(void); + /** * Initializes the config_set `cs`. */ @@ -520,6 +525,11 @@ int git_configset_get_string_multi(struct config_set *cs, const char *key, */ void git_configset_clear(struct config_set *cs); +/** + * Clears and frees a heap-allocated `config_set` structure. + */ +void git_configset_clear_and_free(struct config_set *cs); + /* * These functions return 1 if not found, and 0 if found, leaving the found * value in the 'dest' pointer. From patchwork Fri Aug 9 22:41:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 13759296 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48D9016CD06 for ; Fri, 9 Aug 2024 22:41:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243291; cv=none; b=Fd7dKXuCNxQYMbohn6cjfclomlEabFpywEMIyemZ2NiPp4097WOTEkgNrE6luTdCjKTYWXjViFPpjT2zjhFkfizsPr3tNeIn1J4wDo+jY978JypJoXUb/c1JXk/TXmG37HkEEZ4o9KVSXKkYBRS21ujI6aW34VaKamUKgvatDUY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723243291; c=relaxed/simple; bh=3Aq3yBvTj/xxtcZcNNZoTbAHdQxIvUpuRe2xhTaBf3g=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=IE4mpX0PiqpBkxU0EhPxkEXF6g/sXRAZZ0EB1L7EyW6zMy5lv92GvQTVOybnJCfIVUgEuWY9U/REdxRfL/otkkoVYZRQChsVakuMnIhcOVO6MKjEzXLGVpv1BPCBhYLo3GzoQ9F1bicocnDa2pydfQaZt/AabQTqjlyvquNrIdk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=XV+6Vobh; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--steadmon.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="XV+6Vobh" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-666010fb35cso40563837b3.0 for ; Fri, 09 Aug 2024 15:41:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1723243288; x=1723848088; 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=DzuW0RVZGRG+NSz4paECFTkCfuzaDnsPB3YTEfvFEro=; b=XV+6VobhGmfildMXS2iocQKqosQu0MEyty29QFaBxjCEtyFCiCY7v175Gumx9VpEUY KmRSDl5yZioGpE6NMPpUNARtuX2PD73BjVBP35Xk4wxPaFbNDfPtno6thCnHY0vZVE3V l47sQp0fWj4RQDKPZ4OGP1FcCuaPR/M+vMNPZ6a0BTPxf8jA+4SeTIs/5fmsE6umt4G6 ajSkZHoZc4GhQmoIAnbL6nTpcRLVZAFaORb8JERJo/hENRr0aMGLMb2weUVeyjJWsDSJ 4EytZ6C+rYStTKToNSc/BMUOfeA3xo1W9lIds1e/GK1h/8q+vxkpC1y48uH3O6iFn7xO xbRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723243288; x=1723848088; 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=DzuW0RVZGRG+NSz4paECFTkCfuzaDnsPB3YTEfvFEro=; b=OxP0zOgHyILXdiwhddmtjJYEBhnzvzhCXhoIJ44oQ+GPV4PoxCtjVkgWY9/755tvja jLmbabj0k+aEi9SEsBO2ZxzqtNUdtASt06S+SUX8c8viHMIrRbyV6WnIMopN4Vvi7Jm5 TX99+IKSZ2Fl6RzZtUpjFzw7lnlGTumOYfRQavsdRIOZeBe+l1CgpKd8IW4f+2OGYENC 8iUaYroG8+pby7nP3Ru7wZyitx73MtHp3n5Q923Xzwc2PxjJ4KgcWTt5DbHg/l0yY9dd 2SPzS20ZOPtdlY7wUSsVtqYP0ETZRIgy8D88vlRKvJ/sp5OMEhp9nNE7AjKuRsj1Joa1 HtMg== X-Gm-Message-State: AOJu0YxMY7zVJmR2oDiSIQawaDUCOZ0QzmiJwptk8xbgjdItwBTdpJOa bw2qEMcxbh119okHUdVG4h4f/w4XppOPsmidW0LdSwePMSnWg4dlqHHxqhNqE+jhy8hkx1VsV0r yfDUN5DuvBneGhiA+tBNMSNM0QqUFAS4gZvaT6QpyT3IUDQQ3/Em4o39kaVgs/SJMBkua0pCGGP dAG45MmvQu8bbUaelg9adKJsrx2vMNLVAbnwZz4bM= X-Google-Smtp-Source: AGHT+IHj5W0PXbkWYOxhNGw5sSq0ab7r4UQZPfUKitHzXzvlK0ORXi0cItBhIcxPPKrihqVgnQzY1Q4DqgkLzA== X-Received: from lunarfall.svl.corp.google.com ([2620:15c:2d3:204:6126:cc38:1b9:851f]) (user=steadmon job=sendgmr) by 2002:a05:690c:4810:b0:620:32ea:e1d4 with SMTP id 00721157ae682-69ed67fabb5mr508587b3.0.1723243287903; Fri, 09 Aug 2024 15:41:27 -0700 (PDT) Date: Fri, 9 Aug 2024 15:41:17 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog Message-ID: <514c744ba41cf48c4ffd85640b7ef0c5783cc77d.1723242556.git.steadmon@google.com> Subject: [PATCH v2 5/5] cgit: add higher-level cgit crate From: Josh Steadmon To: git@vger.kernel.org Cc: calvinwan@google.com, spectral@google.com, emilyshaffer@google.com, emrass@google.com, rsbecker@nexbridge.com, gitster@pobox.com, mh@glandium.org, sandals@crustytoothpaste.net, Jason@zx2c4.com, dsimic@manjaro.org From: Calvin Wan Wrap `struct config_set` and a few of its associated functions in cgit-sys. Also introduce a higher-level "cgit" crate which provides a more Rust-friendly interface to config_set structs. Co-authored-by: Josh Steadmon Signed-off-by: Calvin Wan Signed-off-by: Josh Steadmon --- .gitignore | 1 + Makefile | 2 +- contrib/cgit-rs/Cargo.lock | 14 ++++ contrib/cgit-rs/Cargo.toml | 10 +++ .../cgit-rs/cgit-sys/public_symbol_export.c | 30 +++++++ .../cgit-rs/cgit-sys/public_symbol_export.h | 12 +++ contrib/cgit-rs/cgit-sys/src/lib.rs | 31 ++++++- contrib/cgit-rs/src/lib.rs | 82 +++++++++++++++++++ 8 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 contrib/cgit-rs/Cargo.lock create mode 100644 contrib/cgit-rs/Cargo.toml create mode 100644 contrib/cgit-rs/src/lib.rs diff --git a/.gitignore b/.gitignore index 567cc9888f..7f2ee89b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -248,4 +248,5 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/cgit-rs/target /contrib/cgit-rs/cgit-sys/target diff --git a/Makefile b/Makefile index db8af99f20..3a71d10fbe 100644 --- a/Makefile +++ b/Makefile @@ -3723,7 +3723,7 @@ clean: profile-clean coverage-clean cocciclean $(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(MAKE) -C Documentation/ clean $(RM) Documentation/GIT-EXCLUDED-PROGRAMS - $(RM) -r contrib/cgit-rs/cgit-sys/target + $(RM) -r contrib/cgit-rs/target contrib/cgit-rs/cgit-sys/target ifndef NO_PERL $(RM) -r perl/build/ endif diff --git a/contrib/cgit-rs/Cargo.lock b/contrib/cgit-rs/Cargo.lock new file mode 100644 index 0000000000..991e775c34 --- /dev/null +++ b/contrib/cgit-rs/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cgit" +version = "0.1.0" +dependencies = [ + "cgit-sys", +] + +[[package]] +name = "cgit-sys" +version = "0.1.0" diff --git a/contrib/cgit-rs/Cargo.toml b/contrib/cgit-rs/Cargo.toml new file mode 100644 index 0000000000..31f4d84522 --- /dev/null +++ b/contrib/cgit-rs/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "cgit" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/lib.rs" + +[dependencies] +cgit-sys = { version = "0.1.0", path = "cgit-sys" } diff --git a/contrib/cgit-rs/cgit-sys/public_symbol_export.c b/contrib/cgit-rs/cgit-sys/public_symbol_export.c index 62a91f76d0..adf8b21f11 100644 --- a/contrib/cgit-rs/cgit-sys/public_symbol_export.c +++ b/contrib/cgit-rs/cgit-sys/public_symbol_export.c @@ -33,6 +33,36 @@ int libgit_parse_maybe_bool(const char *val) return git_parse_maybe_bool(val); } +struct config_set *libgit_configset_alloc(void) +{ + return git_configset_alloc(); +} + +void libgit_configset_clear_and_free(struct config_set *cs) +{ + git_configset_clear_and_free(cs); +} + +void libgit_configset_init(struct config_set *cs) +{ + git_configset_init(cs); +} + +int libgit_configset_add_file(struct config_set *cs, const char *filename) +{ + return git_configset_add_file(cs, filename); +} + +int libgit_configset_get_int(struct config_set *cs, const char *key, int *dest) +{ + return git_configset_get_int(cs, key, dest); +} + +int libgit_configset_get_string(struct config_set *cs, const char *key, char **dest) +{ + return git_configset_get_string(cs, key, dest); +} + const char *libgit_user_agent(void) { return git_user_agent(); diff --git a/contrib/cgit-rs/cgit-sys/public_symbol_export.h b/contrib/cgit-rs/cgit-sys/public_symbol_export.h index 64332f30de..882c7932e8 100644 --- a/contrib/cgit-rs/cgit-sys/public_symbol_export.h +++ b/contrib/cgit-rs/cgit-sys/public_symbol_export.h @@ -9,6 +9,18 @@ void libgit_init_git(const char **argv); int libgit_parse_maybe_bool(const char *val); +struct config_set *libgit_configset_alloc(void); + +void libgit_configset_clear_and_free(struct config_set *cs); + +void libgit_configset_init(struct config_set *cs); + +int libgit_configset_add_file(struct config_set *cs, const char *filename); + +int libgit_configset_get_int(struct config_set *cs, const char *key, int *dest); + +int libgit_configset_get_string(struct config_set *cs, const char *key, char **dest); + const char *libgit_user_agent(void); const char *libgit_user_agent_sanitized(void); diff --git a/contrib/cgit-rs/cgit-sys/src/lib.rs b/contrib/cgit-rs/cgit-sys/src/lib.rs index 8c3ccc2859..d5072ea587 100644 --- a/contrib/cgit-rs/cgit-sys/src/lib.rs +++ b/contrib/cgit-rs/cgit-sys/src/lib.rs @@ -1,6 +1,15 @@ -use std::ffi::{c_char, c_int}; +use std::ffi::{c_char, c_int, c_void}; + +#[allow(non_camel_case_types)] +#[repr(C)] +pub struct config_set { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} extern "C" { + pub fn free(ptr: *mut c_void); + pub fn libgit_setup_git_directory() -> *const c_char; // From config.c @@ -15,6 +24,26 @@ extern "C" { // From version.c pub fn libgit_user_agent() -> *const c_char; pub fn libgit_user_agent_sanitized() -> *const c_char; + + pub fn libgit_configset_alloc() -> *mut config_set; + pub fn libgit_configset_clear_and_free(cs: *mut config_set); + + pub fn libgit_configset_init(cs: *mut config_set); + + pub fn libgit_configset_add_file(cs: *mut config_set, filename: *const c_char) -> c_int; + + pub fn libgit_configset_get_int( + cs: *mut config_set, + key: *const c_char, + int: *mut c_int, + ) -> c_int; + + pub fn libgit_configset_get_string( + cs: *mut config_set, + key: *const c_char, + dest: *mut *mut c_char, + ) -> c_int; + } #[cfg(test)] diff --git a/contrib/cgit-rs/src/lib.rs b/contrib/cgit-rs/src/lib.rs new file mode 100644 index 0000000000..74c83d161a --- /dev/null +++ b/contrib/cgit-rs/src/lib.rs @@ -0,0 +1,82 @@ +use std::ffi::{c_char, c_int, c_void, CStr, CString}; + +use cgit_sys::*; + +pub struct ConfigSet(*mut config_set); +impl ConfigSet { + pub fn new() -> Self { + unsafe { + let ptr = libgit_configset_alloc(); + libgit_configset_init(ptr); + ConfigSet(ptr) + } + } + + // NEEDSWORK: maybe replace &str with &Path + pub fn add_files(&mut self, files: &[&str]) { + for file in files { + let rs = CString::new(*file).expect("Couldn't convert to CString"); + unsafe { + libgit_configset_add_file(self.0, rs.as_ptr()); + } + } + } + + pub fn get_int(&mut self, key: &str) -> Option { + let key = CString::new(key).expect("Couldn't convert to CString"); + let mut val: c_int = 0; + unsafe { + if libgit_configset_get_int(self.0, key.as_ptr(), &mut val as *mut c_int) != 0 { + return None; + } + } + + Some(val) + } + + pub fn get_str(&mut self, key: &str) -> Option { + let key = CString::new(key).expect("Couldn't convert to CString"); + let mut val: *mut c_char = std::ptr::null_mut(); + unsafe { + if libgit_configset_get_string(self.0, key.as_ptr(), &mut val as *mut *mut c_char) != 0 + { + return None; + } + let borrowed_str = CStr::from_ptr(val); + let owned_str = CString::from_vec_with_nul(borrowed_str.to_bytes_with_nul().to_vec()); + free(val as *mut c_void); // Free the xstrdup()ed pointer from the C side + Some(owned_str.unwrap()) + } + } +} + +impl Default for ConfigSet { + fn default() -> Self { + Self::new() + } +} + +impl Drop for ConfigSet { + fn drop(&mut self) { + unsafe { + libgit_configset_clear_and_free(self.0); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn load_configs_via_configset() { + // NEEDSWORK: we need to supply a testdata config + let mut cs = ConfigSet::new(); + let mut path = std::env::home_dir().expect("cannot get home directory path"); + path.push(".gitconfig"); + let path: String = path.into_os_string().into_string().unwrap(); + cs.add_files(&["/etc/gitconfig", ".gitconfig", &path]); + assert_eq!(cs.get_int("trace2.eventNesting"), Some(5)); + assert_eq!(cs.get_str("no_such_config_item"), None); + } +}