Introduce cgit-rs, a Rust wrapper around libgit.a
Subsystems (2)
Re: [PATCH v6 2/5] libgit-sys: introduce Rust wrapper for libgit.a
In reply to Junio C HamanoQuoted 18 lines · Junio C Hamano
Makefile CURL_CONFIG = curl-config · line 661
Quoted 10 lines · Josh Steadmon
Makefile +2
-0@@ -657,6 +657,8 @@ CURL_CONFIG = curl-config GCOV = gcov STRIP = strip SPATCH = spatch +LD = ld +OBJCOPY = objcopyThis assumes GNU binutils is available. As long as our intention is to start the Rust support as an optional feature, that is OK. Hopefully the piece that requires $(OBJCOPY) is arranged to be easily opted out. Let's keep reading.
Quoted 10 lines
Makefile OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS) · line 2736
Quoted 5 lines
Makefile +1
-0@@ -2731,6 +2733,7 @@ OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS) OBJECTS += $(UNIT_TEST_OBJS) OBJECTS += $(CLAR_TEST_OBJS) OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS)) +OBJECTS += contrib/libgit-sys/public_symbol_export.oThis is compiled for everybody, even for those whose platform cannot support Rust interface (or those who choose not to build it). As long as what is in the file is written portably, it is fine to have stubs and entry points that their build will not use.
Later on in the series we add an INCLUDE_LIBGIT_RS variable to control builds and tests; I don't see any reason why we can't move that earlier in the series, so I'll do so in V7 and then look at what we need to do to make things more portable.
Quoted 109 lines
Makefile clean: profile-clean coverage-clean cocciclean · line 3735
Quoted 10 lines
Makefile +4
-0ifndef NO_CURL OBJECTS += http.o http-walker.o remote-curl.o@@ -3726,6 +3729,10 @@ 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/libgit-sys/target + $(RM) -r contrib/libgit-sys/partial_symbol_export.o + $(RM) -r contrib/libgit-sys/hidden_symbol_export.o + $(RM) -r contrib/libgit-sys/libgitpub.aWhich one of the above is a directory? The latter three smells like a regular file, so we shouldn't say "-r" there.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3899
Quoted 7 lines
Makefile +3
-0@@ -3887,3 +3894,12 @@ $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests + +contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a + $(LD) -r $^ -o $@OK. We build a "relocatable" object, which is unconditionally made as part of $(OBJECTS) above. Even without GNU binutils "ld", people hopefully can convince their linker to do the equivalent. I am not sure if it is healthy to assume that such a linker also uses "-r" for the feature, so we may have to make this rule more customizable, or make partial_symbol_export.o only conditionally part of $(OBJECTS) to allow them to opt out.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3902
Quoted 2 lines
Makefile +2
-0+contrib/libgit-sys/hidden_symbol_export.o: contrib/libgit-sys/partial_symbol_export.o + $(OBJCOPY) --localize-hidden $^ $@Unlike the "public" thing, hidden_symbol_export.o was not made part of $(OBJECTS), so this part is arranged to allow people without $(OBJCOPY) to easily opt out of this part of the system, which is good.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3905
Quoted 2 lines
Makefile +2
-0+contrib/libgit-sys/libgitpub.a: contrib/libgit-sys/hidden_symbol_export.o + $(AR) $(ARFLAGS) $@ $^Likewise, people can easily opt out of building "libgitpub.a", which is good (these targets are triggered only from
build.rs).contrib/libgit-sys/README.md line 4
Quoted 10 lines
contrib/libgit-sys/README.md new file +4
-0@@ -0,0 +1,4 @@ +# libgit-sys + +A small proof-of-concept crate showing how to provide a Rust FFI to Git +internals.OK.
contrib/libgit-sys/public_symbol_export.c line 3
Quoted 9 lines
contrib/libgit-sys/public_symbol_export.c new file +3
-0@@ -0,0 +1,21 @@ +// 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 +// avoids conflicts with other libraries such as libgit2. Style.
Quoted 7 lines
contrib/libgit-sys/public_symbol_export.c new file +7
-0+#include "git-compat-util.h" +#include "contrib/libgit-sys/public_symbol_export.h" +#include "version.h" + +#pragma GCC visibility push(default) + +const char *libgit_user_agent (void )contrib/libgit-sys/public_symbol_export.c line 21
Quoted 10 lines
contrib/libgit-sys/public_symbol_export.c new file +10
-0+{ +return git_user_agent (); +} + +const char *libgit_user_agent_sanitized (void ) +{ +return git_user_agent_sanitized (); +} + +#pragma GCC visibility popI do not think we would mind not having Rust binding support on platforms without GCC (and clang---I assume it would be aware of and react to that #pragma GCC the same way?). But do we allow this file to be left uncompiled when the build wants to opt out of Rust support?
Quoted 6 lines
contrib/libgit-sys/public_symbol_export.h new file +0
-0contrib/libgit-sys/public_symbol_export.h line 8
Quoted 8 lines
contrib/libgit-sys/public_symbol_export.h new file +8
-0@@ -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 */ OK.
Re: [PATCH v6 2/5] libgit-sys: introduce Rust wrapper for libgit.a
In reply to Junio C HamanoQuoted 27 lines · Junio C Hamano
contrib/libgit-sys/public_symbol_export.c line 3
Quoted 9 lines · Josh Steadmon
contrib/libgit-sys/public_symbol_export.c new file +3
-0@@ -0,0 +1,21 @@ +// 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 +// avoids conflicts with other libraries such as libgit2. Style.
Quoted 13 lines
contrib/libgit-sys/public_symbol_export.c new file +13
-0+#include "git-compat-util.h" +#include "contrib/libgit-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 ) +{
Quoted 8 lines
contrib/libgit-sys/public_symbol_export.c line 21
Quoted 4 lines
contrib/libgit-sys/public_symbol_export.c new file +4
-0+return git_user_agent_sanitized (); +} + +#pragma GCC visibility popI do not think we would mind not having Rust binding support on platforms without GCC (and clang---I assume it would be aware of and react to that #pragma GCC the same way?).
Yes, GCC and clang both handle this the same way.
Quoted 3 lines
But do we allow this file
to be left uncompiled when the build wants to opt out of Rust support?
Yes, in V7 this will only be built if INCLUDE_LIBGIT_RS is set.
PATCH v6 3/5 libgit-sys: also export some config_set functions
In reply to Josh SteadmonIn preparation for implementing a higher-level Rust API for accessing Git configs, export some of the upstream configset API via libgitpub and libgit-sys. Since this will be exercised as part of the higher-level API in the next commit, no tests have been added for libgit-sys.
While we're at it, add git_configset_alloc() and git_configset_free() functions in libgitpub 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.
--- contrib/libgit-sys/public_symbol_export.c | 29 +++++++++++++++++++++ contrib/libgit-sys/public_symbol_export.h | 10 ++++++++ contrib/libgit-sys/src/lib.rs | 31 ++++++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-)
contrib/libgit-sys/public_symbol_export.c +29 -0
@@ -3,11 +3,40 @@// avoids conflicts with other libraries such as libgit2. #include "git-compat-util.h" +#include "config.h" #include "contrib/libgit-sys/public_symbol_export.h" #include "version.h" #pragma GCC visibility push(default) +struct libgit_config_set *libgit_configset_alloc (void ) +{ +struct config_set *cs =xmalloc (sizeof (struct config_set )); +git_configset_init (cs); +return (struct libgit_config_set *) cs; +} + +void libgit_configset_free (struct libgit_config_set *cs) +{ +git_configset_clear ((struct config_set *) cs); +free ((struct config_set *) cs); +} + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename) +{ +return git_configset_add_file ((struct config_set *) cs, filename); +} + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest) +{ +return git_configset_get_int ((struct config_set *) cs, key, dest); +} + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest) +{ +return git_configset_get_string ((struct config_set *) cs, key, dest); +} +const char *libgit_user_agent (void ) {return git_user_agent ();
contrib/libgit-sys/public_symbol_export.h +10 -0
@@ -1,6 +1,16 @@#ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +struct libgit_config_set *libgit_configset_alloc (void ); + +void libgit_configset_free (struct libgit_config_set *cs); + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename); + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest); + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest); +const char *libgit_user_agent (void );const char *libgit_user_agent_sanitized (void );
contrib/libgit-sys/src/lib.rs +30 -1
@@ -1,15 +1,44 @@#[cfg(has_std__ffi__c_char)] -use std::ffi::c_char; +use std::ffi::{c_char, c_int};#[cfg(not(has_std__ffi__c_char))] #[allow(non_camel_case_types)] pub type c_char =i8 ; +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ; +extern crate libz_sys; +#[allow(non_camel_case_types)] +#[repr( C )] +pub struct libgit_config_set { + _data: [u8 ;0 ], + _marker: core::marker::PhantomData <(*mut u8 , core::marker::PhantomPinned )>, +} +extern "C" {pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ; + +pub fn libgit_configset_alloc () -> *mut libgit_config_set ; +pub fn libgit_configset_free (cs: *mut libgit_config_set ); + +pub fn libgit_configset_add_file (cs: *mut libgit_config_set , filename: *const c_char ) ->c_int ; + +pub fn libgit_configset_get_int ( + cs: *mut libgit_config_set , + key: *const c_char , + int: *mut c_int , + ) ->c_int ; + +pub fn libgit_configset_get_string ( + cs: *mut libgit_config_set , + key: *const c_char , + dest: *mut *mut c_char , + ) ->c_int ; + }#[cfg(test)]
Signature · 1 line
2.48.0.rc2.279.g1de40edade-goog
PATCH v6 4/5 libgit: add higher-level libgit crate
In reply to Josh SteadmonFrom: Calvin Wan <[email protected]>
The C functions exported by libgit-sys do not provide an idiomatic Rust interface. To make it easier to use these functions via Rust, add a higher-level "libgit" crate, that wraps the lower-level configset API with an interface that is more Rust-y.
This combination of $X and $X-sys crates is a common pattern for FFI in Rust, as documented in "The Cargo Book" [1].
[1] https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
--- .gitignore | 1 + Makefile | 2 +- contrib/libgit-rs/Cargo.lock | 77 ++++++++++++++++++++++++ contrib/libgit-rs/Cargo.toml | 15 +++++ contrib/libgit-rs/README.md | 13 ++++ contrib/libgit-rs/build.rs | 4 ++ contrib/libgit-rs/src/lib.rs | 95 ++++++++++++++++++++++++++++++ contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/src/lib.rs | 4 ++ 11 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3
.gitignore +1 -0
@@ -250,4 +250,5 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-rs/target /contrib/libgit-sys/target
Makefile +1 -1
@@ -3729,7 +3729,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/libgit-sys/target + $(RM) -r contrib/libgit-rs/target contrib/libgit-sys/target $(RM) -r contrib/libgit-sys/partial_symbol_export.o $(RM) -r contrib/libgit-sys/hidden_symbol_export.o $(RM) -r contrib/libgit-sys/libgitpub.a
contrib/libgit-rs/Cargo.lock new file +77 -0
77 lines not on this page · raw message
contrib/libgit-rs/Cargo.toml new file +15 -0
@@ -0,0 +1,15 @@ +[package] +name = "libgit" +version = "0.1.0" +edition = "2021" +build = "build.rs" +rust-version = "1.63" + +[lib] +path = "src/lib.rs" + +[dependencies] +libgit-sys = { version = "0.1.0", path = "../libgit-sys" } + +[build-dependencies] +autocfg = "1.4.0"
contrib/libgit-rs/README.md new file +13 -0
@@ -0,0 +1,13 @@ +# libgit-rs + +Proof-of-concept Git bindings for Rust. + +```toml +[dependencies] +libgit = "0.1.0" +``` + +## Rust version requirements + +libgit-rs should support Rust versions at least as old as the version included +in Debian stable (currently 1.63).
contrib/libgit-rs/build.rs new file +4 -0
@@ -0,0 +1,4 @@ +pub fn main () { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); +}
contrib/libgit-rs/src/lib.rs new file +95 -0
95 lines not on this page · raw message
contrib/libgit-rs/testdata/config1 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 1
contrib/libgit-rs/testdata/config2 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventTarget = 1
contrib/libgit-rs/testdata/config3 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 3
contrib/libgit-sys/src/lib.rs +4 -0
@@ -1,3 +1,5 @@ +use std::ffi::c_void; +#[cfg(has_std__ffi__c_char)] use std::ffi::{c_char, c_int};
@@ -19,6 +21,8 @@ pub struct libgit_config_set { }extern "C" { +pub fn free (ptr: *mut c_void ); +pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ;
Signature · 1 line
2.48.0.rc2.279.g1de40edade-goog
Re: [PATCH v6 4/5] libgit: add higher-level libgit crate
Quoted 74 lines · Josh Steadmon
From: Calvin Wan <[email protected]>
contrib/libgit-rs/Cargo.lock new file +67
-0@@ -0,0 +1,77 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libgit" +version = "0.1.0" +dependencies = [ + "autocfg", + "libgit-sys", +] + +[[package]] +name = "libgit-sys" +version = "0.1.0" +dependencies = [ + "autocfg", + "libz-sys", + "make-cmd", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "make-cmd" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]]
contrib/libgit-rs/Cargo.lock line 77
Quoted 10 lines
contrib/libgit-rs/Cargo.lock new file +10
-0+name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
There are two possibilities here. The first is to check in the Cargo.lock, in which case all users will have to use these versions. That produces a more stable and reliable approach, but it has some downsides.
Say, for instance, that a cool new platform or architecture is added to libc and we'd like to support it, but that version of libc requires a newer version of Rust. We then would have to hold off supporting that new platform due to compatibility reasons. But if we omitted the Cargo.lock, users could install any version that meets their needs.
I believe Rust just got the ability to install only versions that honour the rust-version directive in 1.84, whereas older versions will try to use the latest version, even if that fails. So I think it's okay for now to use Cargo.lock, because that means that things will be better out of the box for users on older Rust. But we may want to drop it once 1.84 is older than our supported version.
Quoted 9 lines
contrib/libgit-rs/src/lib.rs new file +3
-0@@ -0,0 +1,95 @@ +use std::ffi::{c_void,CStr ,CString }; +use std::path::Path ; +
contrib/libgit-rs/src/lib.rs line 13
Quoted 10 lines
contrib/libgit-rs/src/lib.rs new file +10
-0+#[cfg(has_std__ffi__c_char)] +use std::ffi::{c_char, c_int}; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_char =i8 ; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ;
By making these pub, you're exporting them. We probably do not want to do that, since they are not part of our API.
If we need them more generally in the code, let's put them in a module called ffi or such that's pub(crate), and then use them from there.
contrib/libgit-rs/src/lib.rs line 18
Quoted 4 lines
contrib/libgit-rs/src/lib.rs new file +4
-0+use libgit_sys::*; + +pub struct ConfigSet (*mut libgit_config_set ); +impl ConfigSet {
I would suggest we place these in a module, such as config. We should expect to have a lot more things in our crate in the future and putting a little thought into this now will make it easier for users in the future.
I'd also, of course, suggest documentation comments, since if we ever upload this to crates.io, people are overwhelmingly going to read only the docs and not the source, and right now we've said nothing about how this works or should work.
Quoted 10 lines
contrib/libgit-rs/src/lib.rs new file +10
-0+#[cfg(test)] +mod tests { +use super ::*; + +#[test] +fn load_configs_via_configset () { +let mut cs =ConfigSet ::new (); + cs.add_files(&[ + Path::new("testdata/config1"), + Path::new("testdata/config2"),
contrib/libgit-rs/src/lib.rs line 95
Quoted 10 lines
contrib/libgit-rs/src/lib.rs new file +10
-0+ Path::new("testdata/config3"), + ]); +// ConfigSet retrieves correct value +assert_eq! (cs.get_int ("trace2.eventTarget" ),Some (1 )); +// ConfigSet respects last config value set +assert_eq! (cs.get_int ("trace2.eventNesting" ),Some (3 )); +// ConfigSet returns None for missing key +assert_eq! (cs.get_string ("foo.bar" ),None ); + } +}
I am, of course, delighted to see tests. This is a nice improvement in our code that we can take advantage of, and we can test both the C code and Rust code at the same time. And if, in the future, we decide that we'd like to implement a Rust-based version of this API to replace the C one, we've already written tests.
Signature · 2 lines
brian m. carlson (they/them or he/him) Toronto, Ontario, CA
Re: [PATCH v6 4/5] libgit: add higher-level libgit crate
Quoted 97 lines · brian m. carlson
Quoted 74 lines · Josh Steadmon
From: Calvin Wan <[email protected]>
contrib/libgit-rs/Cargo.lock new file +67
-0@@ -0,0 +1,77 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libgit" +version = "0.1.0" +dependencies = [ + "autocfg", + "libgit-sys", +] + +[[package]] +name = "libgit-sys" +version = "0.1.0" +dependencies = [ + "autocfg", + "libz-sys", + "make-cmd", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "make-cmd" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]]contrib/libgit-rs/Cargo.lock line 77
Quoted 10 lines
contrib/libgit-rs/Cargo.lock new file +10
-0+name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"There are two possibilities here. The first is to check in the Cargo.lock, in which case all users will have to use these versions. That produces a more stable and reliable approach, but it has some downsides.
Say, for instance, that a cool new platform or architecture is added to libc and we'd like to support it, but that version of libc requires a newer version of Rust. We then would have to hold off supporting that new platform due to compatibility reasons. But if we omitted the Cargo.lock, users could install any version that meets their needs.
Quoted 6 lines
I believe Rust just got the ability to install only versions that honour the rust-version directive in 1.84, whereas older versions will try to use the latest version, even if that fails. So I think it's okay for now to use Cargo.lock, because that means that things will be better out of the box for users on older Rust. But we may want to drop it once 1.84 is older than our supported version.
OK, I'll add a TODO comment in Cargo.toml.
Quoted 14 lines
Quoted 14 lines
contrib/libgit-rs/src/lib.rs new file +8
-0@@ -0,0 +1,95 @@ +use std::ffi::{c_void,CStr ,CString }; +use std::path::Path ; + +#[cfg(has_std__ffi__c_char)] +use std::ffi::{c_char, c_int}; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)]
Quoted 8 lines
contrib/libgit-rs/src/lib.rs line 13
Quoted 5 lines
contrib/libgit-rs/src/lib.rs new file +5
-0+pub type c_char =i8 ; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ;By making these
pub, you're exporting them. We probably do not want to do that, since they are not part of our API.
Fixed for V7.
Quoted 2 lines
If we need them more generally in the code, let's put them in a module called
ffior such that'spub(crate), and then use them from there.
Hmm, I guess we'd need to do that for libgit-sys as well? Or maybe not, since they're part of the API and thus we should just keep the current pub type ... setup?
Quoted 9 lines
contrib/libgit-rs/src/lib.rs line 18
Quoted 4 lines
contrib/libgit-rs/src/lib.rs new file +4
-0+use libgit_sys::*; + +pub struct ConfigSet (*mut libgit_config_set ); +impl ConfigSet {I would suggest we place these in a module, such as
config. We should expect to have a lot more things in our crate in the future and putting a little thought into this now will make it easier for users in the future.
ACK, will do for V7.
Quoted 4 lines
I'd also, of course, suggest documentation comments, since if we ever upload this to crates.io, people are overwhelmingly going to read only the docs and not the source, and right now we've said nothing about how this works or should work.
ACK.
Quoted 18 lines
Quoted 18 lines
contrib/libgit-rs/src/lib.rs new file +18
-0+#[cfg(test)] +mod tests { +use super ::*; + +#[test] +fn load_configs_via_configset () { +let mut cs =ConfigSet ::new (); + cs.add_files (&[ +Path ::new ("testdata/config1" ), +Path ::new ("testdata/config2" ), +Path ::new ("testdata/config3" ), + ]); +// ConfigSet retrieves correct value +assert_eq! (cs.get_int ("trace2.eventTarget" ),Some (1 )); +// ConfigSet respects last config value set +assert_eq! (cs.get_int ("trace2.eventNesting" ),Some (3 )); +// ConfigSet returns None for missing key +assert_eq! (cs.get_string ("foo.bar" ),None );
Quoted 8 lines
contrib/libgit-rs/src/lib.rs line 37
Quoted 2 lines
contrib/libgit-rs/src/lib.rs new file +2
-0+ } +}I am, of course, delighted to see tests. This is a nice improvement in our code that we can take advantage of, and we can test both the C code and Rust code at the same time. And if, in the future, we decide that we'd like to implement a Rust-based version of this API to replace the C one, we've already written tests.
Thanks for the review and advice (both for this round and all the previous ones), it's much appreciated.
Quoted 3 lines
Signature · 2 lines
brian m. carlson (they/them or he/him) Toronto, Ontario, CA
PATCH v6 5/5 Makefile: add option to build and test libgit-rs and libgit-rs-sys
In reply to Josh SteadmonFrom: Calvin Wan <[email protected]>
Add libgitrs, libgitrs-sys, libgitrs-test, and libgitrs-sys-test targets to their respective Makefiles so they can be built and tested without having to run cargo build/test.
Add build variable, INCLUDE_LIBGIT_RS, that when set, automatically builds and tests libgit-rs and libgit-rs-sys when make all is run.
--- Makefile | 26 ++++++++++++++++++++++++++ contrib/libgit-sys/build.rs | 2 +- t/Makefile | 16 ++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-)
Makefile +26 -0
@@ -416,6 +416,9 @@ include shared.mak # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test # programs in oss-fuzz/. # +# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and +# test the Rust crates in contrib/libgit-rs/ and contrib/libgit-rs/libgit-sys/. +# # === Optional library: libintl === # # Define NO_GETTEXT if you don't want Git output to be translated.
@@ -2238,6 +2241,13 @@ ifdef FSMONITOR_OS_SETTINGS COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif +ifdef INCLUDE_LIBGIT_RS + # Enable symbol hiding in contrib/libgit-rs/libgit-sys/libgitpub.a + # without making us rebuild the whole tree every time we run a Rust + # build. + BASIC_CFLAGS += -fvisibility=hidden +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif
@@ -3895,6 +3905,22 @@ build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests +.PHONY: libgit-sys +libgit-sys: + $(QUIET)(\ + cd contrib/libgit-sys && \ + cargo build \ + ) +.PHONY: libgit-rs +libgit-rs: + $(QUIET)(\ + cd contrib/libgit-rs && \ + cargo build \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-rs +endif + contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a $(LD) -r $^ -o $@
contrib/libgit-sys/build.rs +1 -1
@@ -14,7 +14,7 @@ pub fn main() -> std::io::Result<()> { .env_remove("PROFILE") .current_dir (git_root.clone ()) .args ([ -"CFLAGS=-fvisibility=hidden" , +"INCLUDE_LIBGIT_RS=YesPlease" ,"contrib/libgit-sys/libgitpub.a" , ]) .output ()
t/Makefile +16 -0
@@ -177,3 +177,19 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) + +.PHONY: libgit-sys-test +libgit-sys-test: + $(QUIET)(\ + cd ../contrib/libgit-sys && \ + cargo test \ + ) +.PHONY: libgit-rs-test +libgit-rs-test: + $(QUIET)(\ + cd ../contrib/libgit-rs && \ + cargo test \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys-test libgit-rs-test +endif
Signature · 1 line
2.48.0.rc2.279.g1de40edade-goog
Re: [PATCH v6 0/5] Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonQuoted 4 lines · Josh Steadmon
Apologies for the long delay on V6; I am finally back after several months of $DAYJOB firefighting, holidays, and sick leave. I should have time to devote to this series again, but given the lack of feedback on V5 I am hopeful that this will be the final iteration of this series.
Thanks and welcome back ;-)
Given the lack of feedback on the previous round, I hope we will see enthused support on the topic. Otherwise it is hard to tell if the previous lack of feedback was merely lack of interest, or lack of anything lacking in the series.
Quoted 8 lines
There is known NEEDSWORK, but I feel that they can be addressed in follow-up changes, rather than in this series. If you feel otherwise, please let me know:
* Investigate alternative methods of managing symbol visibility & renaming.
* Figure out symbol versioning
OK. Let's see what people find out.
Re: [PATCH v6 0/5] Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonQuoted 14 lines · Josh Steadmon
Apologies for the long delay on V6; I am finally back after several months of $DAYJOB firefighting, holidays, and sick leave. I should have time to devote to this series again, but given the lack of feedback on V5 I am hopeful that this will be the final iteration of this series.
This series provides two small Rust wrapper libraries around parts of
Git: "libgit-sys", which exposes a few functions from libgit.a, and "libgit", which provides a more Rust-friendly interface to some of those functions. In addition to included unit tests, at $DAYJOB we have tested building JJ[1] with our library and used it to replace some of the libgit2-rs uses.
Quoted 8 lines
There is known NEEDSWORK, but I feel that they can be addressed in follow-up changes, rather than in this series. If you feel otherwise, please let me know:
* Investigate alternative methods of managing symbol visibility & renaming.
* Figure out symbol versioning
It looks like we're building a general Rust lib crate and a static library here, so symbol versioning isn't an issue. I expect in the future we may want to provide a shared library, in which case we will indeed want to do that, but I agree that can wait until later.
In any event, I overall think this series is a nice improvement, and I am very enthusiastic about it. (This is mostly for the benefit of Junio, since I think the authors of this series already know that.) Once it lands, I do plan to build on it somewhat.
Signature · 2 lines
brian m. carlson (they/them or he/him) Toronto, Ontario, CA
Re: [PATCH v6 0/5] Introduce libgit-rs, a Rust wrapper around libgit.a
Quoted 9 lines · brian m. carlson
It looks like we're building a general Rust lib crate and a static library here, so symbol versioning isn't an issue. I expect in the future we may want to provide a shared library, in which case we will indeed want to do that, but I agree that can wait until later.
In any event, I overall think this series is a nice improvement, and I am very enthusiastic about it. (This is mostly for the benefit of Junio, since I think the authors of this series already know that.) Once it lands, I do plan to build on it somewhat.
;-) Thanks, I heard you.
v7 cover Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonThis series provides two small Rust wrapper libraries around parts of
Git: "libgit-sys", which exposes a few functions from libgit.a, and "libgit", which provides a more Rust-friendly interface to some of those functions. In addition to included unit tests, at $DAYJOB we have tested building JJ[1] with our library and used it to replace some of the libgit2-rs uses.
[1] https://github.com/jj-vcs/jj
There is known NEEDSWORK, but I feel that they can be addressed in follow-up changes, rather than in this series. If you feel otherwise, please let me know:
* Investigate alternative methods of managing symbol visibility & renaming.
* Figure out symbol versioning
Changes in V7:
* Moved the ConfigSet implementation in libgit-rs to a config module.
* Added doc comments for ConfigSet and its methods.
* Fix meson builds by adding new object files to libgit_sources
* Moved INCLUDE_LIBGIT_RS Makefile changes earlier in the series, so that we can make it optional to compile some of the libgitpub sources. Squashed V6 patch 5/5 into this series' patch 4/4.
* Don't publicly export FFI types in libgit-rs.
* Removed extraneous -r argument to $(RM) in the clean rules.
* Added TODO reminder in Cargo.toml about removing Cargo.lock once we hit a certain minimum supported Rust version.
* Style cleanup in public_symbol_export.c
Changes in V6:
* Rebased onto current master, since V5 was several months old.
* Move libgit-sys out of libgit-rs; while this sort of nesting is common in Rust crates with standalone repositories, it doesn't make as much sense when they're contained in the larger Git project's repo.
* Standardize the naming of some of the Makefile targets to always include a dash in the "-rs" or "-sys" suffixes.
* Clean up READMEs and crate descriptions in preparation for uploading to crates.io.
Changes in V5:
* When building with INCLUDE_LIBGIT_RS defined, add "-fvisibility=hidden" to CFLAGS. This allows us to manage symbol visibility in libgitpub.a without causing make all to rebuild from scratch due to changing CFLAGS.
* Avoid using c_int in the higher-level Rust API.
* Remove libgitpub.a and intermediate files with make clean.
Changes in V4:
* Drop V3 patch #3, which added wrappers around repository initialization and config access. These are not well-libified, and they are not necessary for JJ's proof-of-concept use case, so let's avoid exporting them for now.
* Set a minimum supported Rust version of 1.63. Autodetect whether our Rust version has c_int and c_char types; if not, define them ourselves.
* When building libgitpub.a via build.rs, set DEVELOPER=1 to catch additional errors at build time.
* In build.rs, use the make_cmd crate to portable select the correct invocation of GNU Make.
* Follow naming standards for _alloc() and _free() functions.
* Use String instead of CString in higher-level API.
* Move libgit_configset_alloc() and libgit_configset_free() out of upstream Git, to the libgitpub shim library.
* In libgitpub, initialize libgit_config_set structs in the _alloc() function rather than with a separate _init() function.
* Remove unnecessary comments in libgit-sys showing where the wrapped functions were originally defined.
* Fix clippy lint: don't reborrow configfile path references.
* Various typo fixes and cargo fmt fixes.
Changes in V3:
* Renamed cgit-rs to libgit-rs and cgit-sys to libgit-sys
* Makefile cleanup, particularly adding config.mak options that developers can set to run Rust builds and tests by default (Patch 6)
* Provide testdata configs for unit tests
* ConfigSet API now uses &Path instead of &str -- more ergonomic for Rust users to pass in and errors out if the path string isn't UTF-8
* Fixed unresolved dependency on libz in Cargo.toml
Calvin Wan (1):
libgit: add higher-level libgit crate
Josh Steadmon (3):
common-main: split init and exit code into new files
libgit-sys: introduce Rust wrapper for libgit.a
libgit-sys: also export some config_set functions
.gitignore | 2 + Makefile | 45 +++++++++ common-exit.c | 26 ++++++ common-init.c | 63 +++++++++++++ common-init.h | 6 ++ common-main.c | 83 +---------------- contrib/libgit-rs/Cargo.lock | 77 ++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 ++++ contrib/libgit-rs/README.md | 13 +++ contrib/libgit-rs/build.rs | 4 + contrib/libgit-rs/src/config.rs | 106 ++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/Cargo.lock | 69 ++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 ++++ contrib/libgit-sys/README.md | 4 + contrib/libgit-sys/build.rs | 35 +++++++ contrib/libgit-sys/public_symbol_export.c | 51 +++++++++++ contrib/libgit-sys/public_symbol_export.h | 18 ++++ contrib/libgit-sys/src/lib.rs | 79 ++++++++++++++++ meson.build | 2 + t/Makefile | 15 +++ 24 files changed, 660 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/config.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3 create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644 contrib/libgit-sys/Cargo.toml create mode 100644 contrib/libgit-sys/README.md create mode 100644 contrib/libgit-sys/build.rs create mode 100644 contrib/libgit-sys/public_symbol_export.c create mode 100644 contrib/libgit-sys/public_symbol_export.h create mode 100644 contrib/libgit-sys/src/lib.rs
Range-diff against v6:
1: ff6cd62397 ! 1: cd0cb9aa04 common-main: split init and exit code into new files
@@ common-main.c
-
- return code;
-}
+
+ ## meson.build ##
+@@ meson.build: libgit_sources = [
+ 'commit-graph.c',
+ 'commit-reach.c',
+ 'commit.c',
++ 'common-exit.c',
++ 'common-init.c',
+ 'compat/nonblock.c',
+ 'compat/obstack.c',
+ 'compat/terminal.c',
2: 5fc66cdb16 ! 2: f1502b8590 libgit-sys: introduce Rust wrapper for libgit.a
@@ .gitignore: Release/
+/contrib/libgit-sys/target
## Makefile ##
+@@ Makefile: include shared.mak
+ # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test
+ # programs in oss-fuzz/.
+ #
++# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and
++# test the Rust crate in contrib/libgit-sys.
++#
+ # === Optional library: libintl ===
+ #
+ # Define NO_GETTEXT if you don't want Git output to be translated.
@@ Makefile: CURL_CONFIG = curl-config
GCOV = gcov
STRIP = strip
@@ Makefile: CURL_CONFIG = curl-config
export TCL_PATH TCLTK_PATH
-@@ Makefile: OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS)
- OBJECTS += $(UNIT_TEST_OBJS)
+@@ Makefile: ifdef FSMONITOR_OS_SETTINGS
+ COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o
+ endif
+
++ifdef INCLUDE_LIBGIT_RS
++ # Enable symbol hiding in contrib/libgit-sys/libgitpub.a without making
++ # us rebuild the whole tree every time we run a Rust build.
++ BASIC_CFLAGS += -fvisibility=hidden
++endif
++
+ ifeq ($(TCLTK_PATH),)
+ NO_TCLTK = NoThanks
+ endif
+@@ Makefile: OBJECTS += $(UNIT_TEST_OBJS)
OBJECTS += $(CLAR_TEST_OBJS)
OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
-+OBJECTS += contrib/libgit-sys/public_symbol_export.o
++ifdef INCLUDE_LIBGIT_RS
++ OBJECTS += contrib/libgit-sys/public_symbol_export.o
++endif
++
ifndef NO_CURL
OBJECTS += http.o http-walker.o remote-curl.o
+ endif
@@ Makefile: 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/libgit-sys/target
-+ $(RM) -r contrib/libgit-sys/partial_symbol_export.o
-+ $(RM) -r contrib/libgit-sys/hidden_symbol_export.o
-+ $(RM) -r contrib/libgit-sys/libgitpub.a
++ $(RM) contrib/libgit-sys/partial_symbol_export.o
++ $(RM) contrib/libgit-sys/hidden_symbol_export.o
++ $(RM) contrib/libgit-sys/libgitpub.a
ifndef NO_PERL
$(RM) -r perl/build/
endif
@@ Makefile: $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GIT
unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X
$(MAKE) -C t/ unit-tests
+
++.PHONY: libgit-sys
++libgit-sys:
++ $(QUIET)(\
++ cd contrib/libgit-sys && \
++ cargo build \
++ )
++ifdef INCLUDE_LIBGIT_RS
++all:: libgit-sys
++endif
++
+contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a
+ $(LD) -r $^ -o $@
+
@@ contrib/libgit-sys/Cargo.toml (new)
+edition = "2021"
+build = "build.rs"
+links = "gitpub"
-+rust-version = "1.63"
++rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from
++ # version control. See https://lore.kernel.org/git/[email protected]/
+description = "Native bindings to a portion of libgit"
+
+[lib]
@@ contrib/libgit-sys/build.rs (new)
+ .env_remove("PROFILE")
+ .current_dir(git_root.clone())
+ .args([
-+ "CFLAGS=-fvisibility=hidden",
++ "INCLUDE_LIBGIT_RS=YesPlease",
+ "contrib/libgit-sys/libgitpub.a",
+ ])
+ .output()
@@ contrib/libgit-sys/build.rs (new)
## contrib/libgit-sys/public_symbol_export.c (new) ##
@@
-+// 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
-+// avoids conflicts with other libraries such as libgit2.
++/* 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
++ * avoids conflicts with other libraries such as libgit2.
++ */
+
+#include "git-compat-util.h"
+#include "contrib/libgit-sys/public_symbol_export.h"
@@ contrib/libgit-sys/src/lib.rs (new)
+ );
+ }
+}
+
+ ## t/Makefile ##
+@@ t/Makefile: perf:
+
+ .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \
+ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS)
++
++.PHONY: libgit-sys-test
++libgit-sys-test:
++ $(QUIET)(\
++ cd ../contrib/libgit-sys && \
++ cargo test \
++ )
++ifdef INCLUDE_LIBGIT_RS
++all:: libgit-sys-test
++endif
3: 03f39b6c3a < -: ---------- libgit-sys: also export some config_set functions
5: 84706f0db7 ! 3: d67d3648d1 Makefile: add option to build and test libgit-rs and libgit-rs-sys
@@
## Metadata ##
-Author: Calvin Wan <[email protected]>
+Author: Josh Steadmon <[email protected]>
## Commit message ##
- Makefile: add option to build and test libgit-rs and libgit-rs-sys
+ libgit-sys: also export some config_set functions
- Add libgitrs, libgitrs-sys, libgitrs-test, and libgitrs-sys-test targets
- to their respective Makefiles so they can be built and tested without
- having to run cargo build/test.
+ In preparation for implementing a higher-level Rust API for accessing
+ Git configs, export some of the upstream configset API via libgitpub and
+ libgit-sys. Since this will be exercised as part of the higher-level API
+ in the next commit, no tests have been added for libgit-sys.
- Add build variable, INCLUDE_LIBGIT_RS, that when set, automatically
- builds and tests libgit-rs and libgit-rs-sys when `make all` is run.
+ While we're at it, add git_configset_alloc() and git_configset_free()
+ functions in libgitpub 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: Josh Steadmon <[email protected]>
+ Co-authored-by: Calvin Wan <[email protected]>
Signed-off-by: Calvin Wan <[email protected]>
+ Signed-off-by: Josh Steadmon <[email protected]>
- ## Makefile ##
-@@ Makefile: include shared.mak
- # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test
- # programs in oss-fuzz/.
- #
-+# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and
-+# test the Rust crates in contrib/libgit-rs/ and contrib/libgit-rs/libgit-sys/.
-+#
- # === Optional library: libintl ===
- #
- # Define NO_GETTEXT if you don't want Git output to be translated.
-@@ Makefile: ifdef FSMONITOR_OS_SETTINGS
- COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o
- endif
+ ## contrib/libgit-sys/public_symbol_export.c ##
+@@
+ */
-+ifdef INCLUDE_LIBGIT_RS
-+ # Enable symbol hiding in contrib/libgit-rs/libgit-sys/libgitpub.a
-+ # without making us rebuild the whole tree every time we run a Rust
-+ # build.
-+ BASIC_CFLAGS += -fvisibility=hidden
-+endif
-+
- ifeq ($(TCLTK_PATH),)
- NO_TCLTK = NoThanks
- endif
-@@ Makefile: build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
- unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X
- $(MAKE) -C t/ unit-tests
+ #include "git-compat-util.h"
++#include "config.h"
+ #include "contrib/libgit-sys/public_symbol_export.h"
+ #include "version.h"
-+.PHONY: libgit-sys
-+libgit-sys:
-+ $(QUIET)(\
-+ cd contrib/libgit-sys && \
-+ cargo build \
-+ )
-+.PHONY: libgit-rs
-+libgit-rs:
-+ $(QUIET)(\
-+ cd contrib/libgit-rs && \
-+ cargo build \
-+ )
-+ifdef INCLUDE_LIBGIT_RS
-+all:: libgit-rs
-+endif
-+
- contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a
- $(LD) -r $^ -o $@
+ #pragma GCC visibility push(default)
++struct libgit_config_set *libgit_configset_alloc(void)
++{
++ struct config_set *cs = xmalloc(sizeof(struct config_set));
++ git_configset_init(cs);
++ return (struct libgit_config_set *) cs;
++}
++
++void libgit_configset_free(struct libgit_config_set *cs)
++{
++ git_configset_clear((struct config_set *) cs);
++ free((struct config_set *) cs);
++}
++
++int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename)
++{
++ return git_configset_add_file((struct config_set *) cs, filename);
++}
++
++int libgit_configset_get_int(struct libgit_config_set *cs, const char *key, int *dest)
++{
++ return git_configset_get_int((struct config_set *) cs, key, dest);
++}
++
++int libgit_configset_get_string(struct libgit_config_set *cs, const char *key, char **dest)
++{
++ return git_configset_get_string((struct config_set *) cs, key, dest);
++}
++
+ const char *libgit_user_agent(void)
+ {
+ return git_user_agent();
- ## contrib/libgit-sys/build.rs ##
-@@ contrib/libgit-sys/build.rs: pub fn main() -> std::io::Result<()> {
- .env_remove("PROFILE")
- .current_dir(git_root.clone())
- .args([
-- "CFLAGS=-fvisibility=hidden",
-+ "INCLUDE_LIBGIT_RS=YesPlease",
- "contrib/libgit-sys/libgitpub.a",
- ])
- .output()
+ ## contrib/libgit-sys/public_symbol_export.h ##
+@@
+ #ifndef PUBLIC_SYMBOL_EXPORT_H
+ #define PUBLIC_SYMBOL_EXPORT_H
+
++struct libgit_config_set *libgit_configset_alloc(void);
++
++void libgit_configset_free(struct libgit_config_set *cs);
++
++int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename);
++
++int libgit_configset_get_int(struct libgit_config_set *cs, const char *key, int *dest);
++
++int libgit_configset_get_string(struct libgit_config_set *cs, const char *key, char **dest);
++
+ const char *libgit_user_agent(void);
+
+ const char *libgit_user_agent_sanitized(void);
- ## t/Makefile ##
-@@ t/Makefile: perf:
+ ## contrib/libgit-sys/src/lib.rs ##
+@@
+ #[cfg(has_std__ffi__c_char)]
+-use std::ffi::c_char;
++use std::ffi::{c_char, c_int};
+
+ #[cfg(not(has_std__ffi__c_char))]
+ #[allow(non_camel_case_types)]
+ pub type c_char = i8;
+
++#[cfg(not(has_std__ffi__c_char))]
++#[allow(non_camel_case_types)]
++pub type c_int = i32;
++
+ extern crate libz_sys;
+
++#[allow(non_camel_case_types)]
++#[repr(C)]
++pub struct libgit_config_set {
++ _data: [u8; 0],
++ _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
++}
++
+ extern "C" {
+ pub fn libgit_user_agent() -> *const c_char;
+ pub fn libgit_user_agent_sanitized() -> *const c_char;
++
++ pub fn libgit_configset_alloc() -> *mut libgit_config_set;
++ pub fn libgit_configset_free(cs: *mut libgit_config_set);
++
++ pub fn libgit_configset_add_file(cs: *mut libgit_config_set, filename: *const c_char) -> c_int;
++
++ pub fn libgit_configset_get_int(
++ cs: *mut libgit_config_set,
++ key: *const c_char,
++ int: *mut c_int,
++ ) -> c_int;
++
++ pub fn libgit_configset_get_string(
++ cs: *mut libgit_config_set,
++ key: *const c_char,
++ dest: *mut *mut c_char,
++ ) -> c_int;
++
+ }
- .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \
- check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS)
-+
-+.PHONY: libgit-sys-test
-+libgit-sys-test:
-+ $(QUIET)(\
-+ cd ../contrib/libgit-sys && \
-+ cargo test \
-+ )
-+.PHONY: libgit-rs-test
-+libgit-rs-test:
-+ $(QUIET)(\
-+ cd ../contrib/libgit-rs && \
-+ cargo test \
-+ )
-+ifdef INCLUDE_LIBGIT_RS
-+all:: libgit-sys-test libgit-rs-test
-+endif
+ #[cfg(test)]4: 65166ea0c0 ! 4: 88425bb0b1 libgit: add higher-level libgit crate
@@ .gitignore: Release/
/contrib/libgit-sys/target
## Makefile ##
+@@ Makefile: include shared.mak
+ # programs in oss-fuzz/.
+ #
+ # Define INCLUDE_LIBGIT_RS if you want make all and make test to build and
+-# test the Rust crate in contrib/libgit-sys.
++# test the Rust crates in contrib/libgit-sys and contrib/libgit-rs.
+ #
+ # === Optional library: libintl ===
+ #
@@ Makefile: 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/libgit-sys/target
-+ $(RM) -r contrib/libgit-rs/target contrib/libgit-sys/target
- $(RM) -r contrib/libgit-sys/partial_symbol_export.o
- $(RM) -r contrib/libgit-sys/hidden_symbol_export.o
- $(RM) -r contrib/libgit-sys/libgitpub.a
++ $(RM) -r contrib/libgit-sys/target contrib/libgit-rs/target
+ $(RM) contrib/libgit-sys/partial_symbol_export.o
+ $(RM) contrib/libgit-sys/hidden_symbol_export.o
+ $(RM) contrib/libgit-sys/libgitpub.a
+@@ Makefile: build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
+ unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X
+ $(MAKE) -C t/ unit-tests
+
+-.PHONY: libgit-sys
++.PHONY: libgit-sys libgit-rs
+ libgit-sys:
+ $(QUIET)(\
+ cd contrib/libgit-sys && \
+ cargo build \
+ )
++libgit-rs:
++ $(QUIET)(\
++ cd contrib/libgit-rs && \
++ cargo build \
++ )
+ ifdef INCLUDE_LIBGIT_RS
+-all:: libgit-sys
++all:: libgit-sys libgit-rs
+ endif
+
+ contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a
## contrib/libgit-rs/Cargo.lock (new) ##
@@
@@ contrib/libgit-rs/Cargo.toml (new)
+version = "0.1.0"
+edition = "2021"
+build = "build.rs"
-+rust-version = "1.63"
++rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from
++ # version control. See https://lore.kernel.org/git/[email protected]/
++
+
+[lib]
+path = "src/lib.rs"
@@ contrib/libgit-rs/build.rs (new)
+ ac.emit_has_path("std::ffi::c_char");
+}
- ## contrib/libgit-rs/src/lib.rs (new) ##
+ ## contrib/libgit-rs/src/config.rs (new) ##
@@
+use std::ffi::{c_void, CStr, CString};
+use std::path::Path;
@@ contrib/libgit-rs/src/lib.rs (new)
+
+#[cfg(not(has_std__ffi__c_char))]
+#[allow(non_camel_case_types)]
-+pub type c_char = i8;
++type c_char = i8;
+
+#[cfg(not(has_std__ffi__c_char))]
+#[allow(non_camel_case_types)]
-+pub type c_int = i32;
++type c_int = i32;
+
+use libgit_sys::*;
+
++/// A ConfigSet is an in-memory cache for config-like files such as .gitmodules or .gitconfig. ++/// It does not support all config directives; notably, it will not process include or ++/// includeIf directives (but it will store them so that callers can choose whether and how to ++/// handle them).
+pub struct ConfigSet(*mut libgit_config_set);
+impl ConfigSet {
++ /// Allocate a new ConfigSet
+ pub fn new() -> Self {
+ unsafe { ConfigSet(libgit_configset_alloc()) }
+ }
+
++ /// Load the given files into the ConfigSet; conflicting directives in later files will
++ /// override those given in earlier files.
+ pub fn add_files(&mut self, files: &[&Path]) {
+ for file in files {
+ let pstr = file.to_str().expect("Invalid UTF-8");
@@ contrib/libgit-rs/src/lib.rs (new)
+ }
+ }
+
++ /// Load the value for the given key and attempt to parse it as an i32. Dies with a fatal error
++ /// if the value cannot be parsed. Returns None if the key is not present.
+ pub fn get_int(&mut self, key: &str) -> Option<i32> {
+ let key = CString::new(key).expect("Couldn't convert to CString");
+ let mut val: c_int = 0;
@@ contrib/libgit-rs/src/lib.rs (new)
+ Some(val.into())
+ }
+
++ /// Clones the value for the given key. Dies with a fatal error if the value cannot be
++ /// converted to a String. Returns None if the key is not present.
+ pub fn get_string(&mut self, key: &str) -> Option<String> {
+ let key = CString::new(key).expect("Couldn't convert key to CString");
+ let mut val: *mut c_char = std::ptr::null_mut();
@@ contrib/libgit-rs/src/lib.rs (new)
+ }
+}
+ ## contrib/libgit-rs/src/lib.rs (new) ##
+@@
++pub mod config;
+
## contrib/libgit-rs/testdata/config1 (new) ##
@@
+[trace2]
@@ contrib/libgit-sys/src/lib.rs: pub struct libgit_config_set {
pub fn libgit_user_agent() -> *const c_char; pub fn libgit_user_agent_sanitized() -> *const c_char;
+
+ ## t/Makefile ##
+@@ t/Makefile: perf:
+ .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \
+ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS)
+
+-.PHONY: libgit-sys-test
++.PHONY: libgit-sys-test libgit-rs-test
+ libgit-sys-test:
+ $(QUIET)(\
+ cd ../contrib/libgit-sys && \
+ cargo test \
+ )
++libgit-rs-test:
++ $(QUIET)(\
++ cd ../contrib/libgit-rs && \
++ cargo test \
++ )
+ ifdef INCLUDE_LIBGIT_RS
+-all:: libgit-sys-test
++all:: libgit-sys-test libgit-rs-test
+ endif
base-commit: 757161efcca150a9a96b312d9e780a071e601a03
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
PATCH v7 1/4 common-main: split init and exit code into new files
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/[email protected]/
[2] https://lore.kernel.org/git/[email protected]/
--- Makefile | 2 ++ common-exit.c | 26 ++++++++++++++++ common-init.c | 63 ++++++++++++++++++++++++++++++++++++++ common-init.h | 6 ++++ common-main.c | 83 ++------------------------------------------------- meson.build | 2 ++ 6 files changed, 101 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h
Makefile +2 -0
@@ -981,6 +981,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
common-exit.c new file +26 -0
@@ -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; +}
common-init.c new file +63 -0
63 lines not on this page · raw message
common-init.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef COMMON_INIT_H +#define COMMON_INIT_H + +void init_git (const char **argv); + +#endif /* COMMON_INIT_H */
common-main.c +2 -81
94 lines not on this page · raw message
meson.build +2 -0
@@ -245,6 +245,8 @@ libgit_sources = [ 'commit-graph.c', 'commit-reach.c', 'commit.c', + 'common-exit.c', + 'common-init.c', 'compat/nonblock.c', 'compat/obstack.c', 'compat/terminal.c',
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
PATCH v7 2/4 libgit-sys: introduce Rust wrapper for libgit.a
In reply to Josh SteadmonIntroduce libgit-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 containing a more Rust-friendly interface will be added at contrib/libgit-rs.
Symbols in libgit 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/libgit-rs/libgit-sys/libgitpub.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.
--- .gitignore | 1 + Makefile | 38 +++++++++++++ contrib/libgit-sys/Cargo.lock | 69 +++++++++++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 +++++++ contrib/libgit-sys/README.md | 4 ++ contrib/libgit-sys/build.rs | 35 ++++++++++++ contrib/libgit-sys/public_symbol_export.c | 22 ++++++++ contrib/libgit-sys/public_symbol_export.h | 8 +++ contrib/libgit-sys/src/lib.rs | 46 +++++++++++++++ t/Makefile | 10 ++++ 10 files changed, 252 insertions(+) create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644 contrib/libgit-sys/Cargo.toml create mode 100644 contrib/libgit-sys/README.md create mode 100644 contrib/libgit-sys/build.rs create mode 100644 contrib/libgit-sys/public_symbol_export.c create mode 100644 contrib/libgit-sys/public_symbol_export.h create mode 100644 contrib/libgit-sys/src/lib.rs
.gitignore +1 -0
@@ -250,3 +250,4 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-sys/target
Makefile +38 -0
@@ -416,6 +416,9 @@ include shared.mak # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test # programs in oss-fuzz/. # +# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and +# test the Rust crate in contrib/libgit-sys. +# # === Optional library: libintl === # # Define NO_GETTEXT if you don't want Git output to be translated.
@@ -657,6 +660,8 @@ CURL_CONFIG = curl-config GCOV = gcov STRIP = strip SPATCH = spatch +LD = ld +OBJCOPY = objcopy export TCL_PATH TCLTK_PATH
@@ -2236,6 +2241,12 @@ ifdef FSMONITOR_OS_SETTINGS COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif +ifdef INCLUDE_LIBGIT_RS + # Enable symbol hiding in contrib/libgit-sys/libgitpub.a without making + # us rebuild the whole tree every time we run a Rust build. + BASIC_CFLAGS += -fvisibility=hidden +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif
@@ -2732,6 +2743,10 @@ OBJECTS += $(UNIT_TEST_OBJS) OBJECTS += $(CLAR_TEST_OBJS) OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS)) +ifdef INCLUDE_LIBGIT_RS + OBJECTS += contrib/libgit-sys/public_symbol_export.o +endif + ifndef NO_CURL OBJECTS += http.o http-walker.o remote-curl.o endif
@@ -3726,6 +3741,10 @@ 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/libgit-sys/target + $(RM) contrib/libgit-sys/partial_symbol_export.o + $(RM) contrib/libgit-sys/hidden_symbol_export.o + $(RM) contrib/libgit-sys/libgitpub.a ifndef NO_PERL $(RM) -r perl/build/ endif
@@ -3887,3 +3906,22 @@ $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests + +.PHONY: libgit-sys +libgit-sys: + $(QUIET)(\ + cd contrib/libgit-sys && \ + cargo build \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys +endif + +contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a + $(LD) -r $^ -o $@ + +contrib/libgit-sys/hidden_symbol_export.o: contrib/libgit-sys/partial_symbol_export.o + $(OBJCOPY) --localize-hidden $^ $@ + +contrib/libgit-sys/libgitpub.a: contrib/libgit-sys/hidden_symbol_export.o + $(AR) $(ARFLAGS) $@ $^
contrib/libgit-sys/Cargo.lock new file +69 -0
69 lines not on this page · raw message
contrib/libgit-sys/Cargo.toml new file +19 -0
@@ -0,0 +1,19 @@ +[package] +name = "libgit-sys" +version = "0.1.0" +edition = "2021" +build = "build.rs" +links = "gitpub" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/[email protected]/ +description = "Native bindings to a portion of libgit" + +[lib] +path = "src/lib.rs" + +[dependencies] +libz-sys = "1.1.19" + +[build-dependencies] +autocfg = "1.4.0" +make-cmd = "0.1.0"
contrib/libgit-sys/README.md new file +4 -0
@@ -0,0 +1,4 @@ +# libgit-sys + +A small proof-of-concept crate showing how to provide a Rust FFI to Git +internals.
contrib/libgit-sys/build.rs new file +35 -0
@@ -0,0 +1,35 @@ +use std::env; +use std::path::PathBuf ; + +pub fn main () -> std::io::Result <()> { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); + +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 = make_cmd::gnu_make () + .env ("DEVELOPER" ,"1" ) + .env_remove ("PROFILE" ) + .current_dir (git_root.clone ()) + .args ([ +"INCLUDE_LIBGIT_RS=YesPlease" , +"contrib/libgit-sys/libgitpub.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 ("libgitpub.a" ), dst.join ("libgitpub.a" ))?; +println! ("cargo:rustc-link-search=native={}" , dst.display ()); +println! ("cargo:rustc-link-lib=gitpub" ); +println! ("cargo:rerun-if-changed={}" , git_root.display ()); + +Ok (()) +}
contrib/libgit-sys/public_symbol_export.c new file +22 -0
@@ -0,0 +1,22 @@ +/* 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 +* avoids conflicts with other libraries such as libgit2. +*/ + +#include "git-compat-util.h" +#include "contrib/libgit-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
contrib/libgit-sys/public_symbol_export.h new file +8 -0
@@ -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 */
contrib/libgit-sys/src/lib.rs new file +46 -0
46 lines not on this page · raw message
t/Makefile +10 -0
@@ -177,3 +177,13 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) + +.PHONY: libgit-sys-test +libgit-sys-test: + $(QUIET)(\ + cd ../contrib/libgit-sys && \ + cargo test \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys-test +endif
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
Re: [PATCH v7 2/4] libgit-sys: introduce Rust wrapper for libgit.a
Quoted 4 lines · Josh Steadmon
Introduce libgit-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.
It's great to see some tests. This is looking good, I've left a couple of small comments below.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3921
Quoted 2 lines
Makefile +2
-0+contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a + $(LD) -r $^ -o $@
This is a very long line and the ones below are pretty long - perhaps we could put the list of sources in a variable?
contrib/libgit-sys/public_symbol_export.c line 1
Quoted 13 lines
Makefile +5
-0+contrib/libgit-sys/hidden_symbol_export.o: contrib/libgit-sys/partial_symbol_export.o + $(OBJCOPY) --localize-hidden $^ $@ + +contrib/libgit-sys/libgitpub.a: contrib/libgit-sys/hidden_symbol_export.o + $(AR) $(ARFLAGS) $@ $^contrib/libgit-sys/public_symbol_export.c new file +1
-0@@ -0,0 +1,22 @@ +/* Shim to publicly export Git symbols. These must be renamed so that the
Style: Multiline comments start with an empty "/*" so this should be
/*
* Shim ...
contrib/libgit-sys/public_symbol_export.c line 4
Quoted 3 lines
contrib/libgit-sys/public_symbol_export.c new file +3
-0+* original symbols can be hidden. Renaming these with a "libgit_" prefix also +* avoids conflicts with other libraries such as libgit2. +*/
Best Wishes
Phillip
Quoted 101 lines
contrib/libgit-sys/public_symbol_export.c new file +17
-0+#include "git-compat-util.h" +#include "contrib/libgit-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 popcontrib/libgit-sys/public_symbol_export.h new file +8
-0@@ -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 */ contrib/libgit-sys/src/lib.rs new file +46
-0@@ -0,0 +1,46 @@ +#[cfg(has_std__ffi__c_char)] +use std::ffi::c_char; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_char =i8 ; + +extern crate libz_sys; + +extern "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 + ); + } +}t/Makefile +10
-0@@ -177,3 +177,13 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) + +.PHONY: libgit-sys-test +libgit-sys-test: + $(QUIET)(\ + cd ../contrib/libgit-sys && \ + cargo test \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys-test +endif
Re: [PATCH v7 2/4] libgit-sys: introduce Rust wrapper for libgit.a
Quoted 8 lines · Phillip Wood
Quoted 4 lines · Josh Steadmon
Introduce libgit-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.
Quoted 8 lines
It's great to see some tests. This is looking good, I've left a couple of small comments below.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3921
Quoted 2 lines
Makefile +2
-0+contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a + $(LD) -r $^ -o $@This is a very long line and the ones below are pretty long - perhaps we could put the list of sources in a variable?
Done for V8.
Quoted 16 lines
contrib/libgit-sys/public_symbol_export.c line 1
Quoted 13 lines
Makefile +5
-0+contrib/libgit-sys/hidden_symbol_export.o: contrib/libgit-sys/partial_symbol_export.o + $(OBJCOPY) --localize-hidden $^ $@ + +contrib/libgit-sys/libgitpub.a: contrib/libgit-sys/hidden_symbol_export.o + $(AR) $(ARFLAGS) $@ $^contrib/libgit-sys/public_symbol_export.c new file +1
-0@@ -0,0 +1,22 @@ +/* Shim to publicly export Git symbols. These must be renamed so that the Style: Multiline comments start with an empty "/*" so this should be
Quoted 2 lines
/*
* Shim ...
Whoops, fixed, thanks.
Re: [PATCH v7 2/4] libgit-sys: introduce Rust wrapper for libgit.a
Quoted 37 lines · Josh Steadmon
Quoted 8 lines · Phillip Wood
Quoted 4 lines · Josh Steadmon
Introduce libgit-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.Quoted 8 lines
It's great to see some tests. This is looking good, I've left a couple of small comments below.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3921
Quoted 2 lines
Makefile +2
-0+contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a + $(LD) -r $^ -o $@This is a very long line and the ones below are pretty long - perhaps we could put the list of sources in a variable?
Done for V8.
Quoted 16 lines
contrib/libgit-sys/public_symbol_export.c line 1
Quoted 13 lines
Makefile +5
-0+contrib/libgit-sys/hidden_symbol_export.o: contrib/libgit-sys/partial_symbol_export.o + $(OBJCOPY) --localize-hidden $^ $@ + +contrib/libgit-sys/libgitpub.a: contrib/libgit-sys/hidden_symbol_export.o + $(AR) $(ARFLAGS) $@ $^contrib/libgit-sys/public_symbol_export.c new file +1
-0@@ -0,0 +1,22 @@ +/* Shim to publicly export Git symbols. These must be renamed so that the Style: Multiline comments start with an empty "/*" so this should be
Quoted 4 lines
Quoted 2 lines
/*
* Shim ...Whoops, fixed, thanks.
The series is looking good and it seems that we'll be expecting a hopefully small and final reroll? I'll mark the topic in the "What's cooking" draft as such.
Thanks, all.
PATCH v7 3/4 libgit-sys: also export some config_set functions
In reply to Josh SteadmonIn preparation for implementing a higher-level Rust API for accessing Git configs, export some of the upstream configset API via libgitpub and libgit-sys. Since this will be exercised as part of the higher-level API in the next commit, no tests have been added for libgit-sys.
While we're at it, add git_configset_alloc() and git_configset_free() functions in libgitpub 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.
--- contrib/libgit-sys/public_symbol_export.c | 29 +++++++++++++++++++++ contrib/libgit-sys/public_symbol_export.h | 10 ++++++++ contrib/libgit-sys/src/lib.rs | 31 ++++++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-)
contrib/libgit-sys/public_symbol_export.c +29 -0
@@ -4,11 +4,40 @@*/ #include "git-compat-util.h" +#include "config.h" #include "contrib/libgit-sys/public_symbol_export.h" #include "version.h" #pragma GCC visibility push(default) +struct libgit_config_set *libgit_configset_alloc (void ) +{ +struct config_set *cs =xmalloc (sizeof (struct config_set )); +git_configset_init (cs); +return (struct libgit_config_set *) cs; +} + +void libgit_configset_free (struct libgit_config_set *cs) +{ +git_configset_clear ((struct config_set *) cs); +free ((struct config_set *) cs); +} + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename) +{ +return git_configset_add_file ((struct config_set *) cs, filename); +} + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest) +{ +return git_configset_get_int ((struct config_set *) cs, key, dest); +} + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest) +{ +return git_configset_get_string ((struct config_set *) cs, key, dest); +} +const char *libgit_user_agent (void ) {return git_user_agent ();
contrib/libgit-sys/public_symbol_export.h +10 -0
@@ -1,6 +1,16 @@#ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +struct libgit_config_set *libgit_configset_alloc (void ); + +void libgit_configset_free (struct libgit_config_set *cs); + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename); + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest); + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest); +const char *libgit_user_agent (void );const char *libgit_user_agent_sanitized (void );
contrib/libgit-sys/src/lib.rs +30 -1
@@ -1,15 +1,44 @@#[cfg(has_std__ffi__c_char)] -use std::ffi::c_char; +use std::ffi::{c_char, c_int};#[cfg(not(has_std__ffi__c_char))] #[allow(non_camel_case_types)] pub type c_char =i8 ; +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ; +extern crate libz_sys; +#[allow(non_camel_case_types)] +#[repr( C )] +pub struct libgit_config_set { + _data: [u8 ;0 ], + _marker: core::marker::PhantomData <(*mut u8 , core::marker::PhantomPinned )>, +} +extern "C" {pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ; + +pub fn libgit_configset_alloc () -> *mut libgit_config_set ; +pub fn libgit_configset_free (cs: *mut libgit_config_set ); + +pub fn libgit_configset_add_file (cs: *mut libgit_config_set , filename: *const c_char ) ->c_int ; + +pub fn libgit_configset_get_int ( + cs: *mut libgit_config_set , + key: *const c_char , + int: *mut c_int , + ) ->c_int ; + +pub fn libgit_configset_get_string ( + cs: *mut libgit_config_set , + key: *const c_char , + dest: *mut *mut c_char , + ) ->c_int ; + }#[cfg(test)]
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
Re: [PATCH v7 3/4] libgit-sys: also export some config_set functions
Hi Josh
Quoted 9 lines · Josh Steadmon
In preparation for implementing a higher-level Rust API for accessing Git configs, export some of the upstream configset API via libgitpub and libgit-sys. Since this will be exercised as part of the higher-level API in the next commit, no tests have been added for libgit-sys.
While we're at it, add
git_configset_alloc()andgit_configset_free()functions in libgitpub so that callers can manageconfig_setstructs on the heap. This also allows non-C external consumers to treatconfig_setsas opaque structs.
This interface is looks nice, I've left a couple of comments below
contrib/libgit-sys/public_symbol_export.c line 11
Quoted 13 lines
contrib/libgit-sys/public_symbol_export.c +1
-0@@ -4,11 +4,40 @@*/ #include "git-compat-util.h" +#include "config.h" #include "contrib/libgit-sys/public_symbol_export.h" #include "version.h" #pragma GCC visibility push(default)
Personally I'd prefer it if we actually defined struct libgit_config_set here
struct libgit_config_set {
struct config_set cs;
}Then we could avoid all the casts below. For example
struct libgit_config_set *libgit_configset_alloc(void)
{
struct libget_config_set *cs =
xmalloc(sizeof(struct libgit_config_set));
git_configset_init(&cs->cs);
return cs;
}Quoted 9 lines
contrib/libgit-sys/public_symbol_export.c +9
-0+struct libgit_config_set *libgit_configset_alloc (void ) +{ +struct config_set *cs =xmalloc (sizeof (struct config_set )); +git_configset_init (cs); +return (struct libgit_config_set *) cs; +} + +void libgit_configset_free (struct libgit_config_set *cs) +{
contrib/libgit-sys/public_symbol_export.c line 31
Quoted 10 lines
contrib/libgit-sys/public_symbol_export.c +10
-0+git_configset_clear ((struct config_set *) cs); +free ((struct config_set *) cs); +} + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename) +{ +return git_configset_add_file ((struct config_set *) cs, filename); +} + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest)
Style: this and the one below could do with being wrapped at 80 characters
This whole series looks pretty good to me
Best Wishes
Phillip
Quoted 83 lines
contrib/libgit-sys/public_symbol_export.c +9
-0+{ +return git_configset_get_int ((struct config_set *) cs, key, dest); +} + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest) +{ +return git_configset_get_string ((struct config_set *) cs, key, dest); +} +const char *libgit_user_agent (void ) {return git_user_agent ();contrib/libgit-sys/public_symbol_export.h +10
-0@@ -1,6 +1,16 @@#ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +struct libgit_config_set *libgit_configset_alloc (void ); + +void libgit_configset_free (struct libgit_config_set *cs); + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename); + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest); + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest); +const char *libgit_user_agent (void );const char *libgit_user_agent_sanitized (void );contrib/libgit-sys/src/lib.rs +30
-1@@ -1,15 +1,44 @@#[cfg(has_std__ffi__c_char)] -use std::ffi::c_char; +use std::ffi::{c_char, c_int};#[cfg(not(has_std__ffi__c_char))] #[allow(non_camel_case_types)] pub type c_char =i8 ; +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ; +extern crate libz_sys; +#[allow(non_camel_case_types)] +#[repr( C )] +pub struct libgit_config_set { + _data: [u8 ;0 ], + _marker: core::marker::PhantomData <(*mut u8 , core::marker::PhantomPinned )>, +} +extern "C" {pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ; + +pub fn libgit_configset_alloc () -> *mut libgit_config_set ; +pub fn libgit_configset_free (cs: *mut libgit_config_set ); + +pub fn libgit_configset_add_file (cs: *mut libgit_config_set , filename: *const c_char ) ->c_int ; + +pub fn libgit_configset_get_int ( + cs: *mut libgit_config_set , + key: *const c_char , + int: *mut c_int , + ) ->c_int ; + +pub fn libgit_configset_get_string ( + cs: *mut libgit_config_set , + key: *const c_char , + dest: *mut *mut c_char , + ) ->c_int ; + }#[cfg(test)]
Re: [PATCH v7 3/4] libgit-sys: also export some config_set functions
Quoted 36 lines · Phillip Wood
Hi Josh
Quoted 9 lines · Josh Steadmon
In preparation for implementing a higher-level Rust API for accessing Git configs, export some of the upstream configset API via libgitpub and libgit-sys. Since this will be exercised as part of the higher-level API in the next commit, no tests have been added for libgit-sys.
While we're at it, add
git_configset_alloc()andgit_configset_free()functions in libgitpub so that callers can manageconfig_setstructs on the heap. This also allows non-C external consumers to treatconfig_setsas opaque structs.This interface is looks nice, I've left a couple of comments below
contrib/libgit-sys/public_symbol_export.c line 9
Quoted 11 lines
contrib/libgit-sys/public_symbol_export.c +1
-0@@ -4,11 +4,40 @@*/ #include "git-compat-util.h" +#include "config.h" #include "contrib/libgit-sys/public_symbol_export.h" #include "version.h" #pragma GCC visibility push(default)Personally I'd prefer it if we actually defined struct
libgit_config_setherestruct libgit_config_set { struct config_set cs; }Then we could avoid all the casts below. For example
Quoted 7 lines
struct
libgit_config_set*libgit_configset_alloc(void){ struct libget_config_set *cs = xmalloc(sizeof(struct libgit_config_set)); git_configset_init(&cs->cs); return cs; }
Hmm yeah I remember this feedback from (checks Lore) back in V2. I think you're right, we should have gone this way from the beginning. Done in V8.
Quoted 13 lines
Quoted 13 lines
contrib/libgit-sys/public_symbol_export.c +13
-0+struct libgit_config_set *libgit_configset_alloc (void ) +{ +struct config_set *cs =xmalloc (sizeof (struct config_set )); +git_configset_init (cs); +return (struct libgit_config_set *) cs; +} + +void libgit_configset_free (struct libgit_config_set *cs) +{ +git_configset_clear ((struct config_set *) cs); +free ((struct config_set *) cs); +} +
Quoted 8 lines
contrib/libgit-sys/public_symbol_export.c line 31
Quoted 6 lines
contrib/libgit-sys/public_symbol_export.c +6
-0+int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename) +{ +return git_configset_add_file ((struct config_set *) cs, filename); +} + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest)Style: this and the one below could do with being wrapped at 80 characters
Fixed.
Quoted 5 lines
This whole series looks pretty good to me
Best Wishes
Phillip
PATCH v7 4/4 libgit: add higher-level libgit crate
In reply to Josh SteadmonFrom: Calvin Wan <[email protected]>
The C functions exported by libgit-sys do not provide an idiomatic Rust interface. To make it easier to use these functions via Rust, add a higher-level "libgit" crate, that wraps the lower-level configset API with an interface that is more Rust-y.
This combination of $X and $X-sys crates is a common pattern for FFI in Rust, as documented in "The Cargo Book" [1].
[1] https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
--- .gitignore | 1 + Makefile | 13 ++-- contrib/libgit-rs/Cargo.lock | 77 +++++++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 +++++ contrib/libgit-rs/README.md | 13 ++++ contrib/libgit-rs/build.rs | 4 ++ contrib/libgit-rs/src/config.rs | 106 +++++++++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/src/lib.rs | 4 ++ t/Makefile | 9 ++- 13 files changed, 245 insertions(+), 6 deletions(-) create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/config.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3
.gitignore +1 -0
@@ -250,4 +250,5 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-rs/target /contrib/libgit-sys/target
Makefile +9 -4
@@ -417,7 +417,7 @@ include shared.mak # programs in oss-fuzz/. # # Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and -# test the Rust crate in contrib/libgit-sys. +# test the Rust crates in contrib/libgit-sys and contrib/libgit-rs. # # === Optional library: libintl === #
@@ -3741,7 +3741,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/libgit-sys/target + $(RM) -r contrib/libgit-sys/target contrib/libgit-rs/target $(RM) contrib/libgit-sys/partial_symbol_export.o $(RM) contrib/libgit-sys/hidden_symbol_export.o $(RM) contrib/libgit-sys/libgitpub.a
@@ -3907,14 +3907,19 @@ build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests -.PHONY: libgit-sys +.PHONY: libgit-sys libgit-rs libgit-sys: $(QUIET)(\ cd contrib/libgit-sys && \ cargo build \ ) +libgit-rs: + $(QUIET)(\ + cd contrib/libgit-rs && \ + cargo build \ + ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys +all:: libgit-sys libgit-rs endif contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a
contrib/libgit-rs/Cargo.lock new file +77 -0
77 lines not on this page · raw message
contrib/libgit-rs/Cargo.toml new file +17 -0
@@ -0,0 +1,17 @@ +[package] +name = "libgit" +version = "0.1.0" +edition = "2021" +build = "build.rs" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/[email protected]/ + + +[lib] +path = "src/lib.rs" + +[dependencies] +libgit-sys = { version = "0.1.0", path = "../libgit-sys" } + +[build-dependencies] +autocfg = "1.4.0"
contrib/libgit-rs/README.md new file +13 -0
@@ -0,0 +1,13 @@ +# libgit-rs + +Proof-of-concept Git bindings for Rust. + +```toml +[dependencies] +libgit = "0.1.0" +``` + +## Rust version requirements + +libgit-rs should support Rust versions at least as old as the version included +in Debian stable (currently 1.63).
contrib/libgit-rs/build.rs new file +4 -0
@@ -0,0 +1,4 @@ +pub fn main () { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); +}
contrib/libgit-rs/src/config.rs new file +106 -0
106 lines not on this page · raw message
contrib/libgit-rs/src/lib.rs new file +1 -0
@@ -0,0 +1 @@ +pub mod config;
contrib/libgit-rs/testdata/config1 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 1
contrib/libgit-rs/testdata/config2 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventTarget = 1
contrib/libgit-rs/testdata/config3 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 3
contrib/libgit-sys/src/lib.rs +4 -0
@@ -1,3 +1,5 @@ +use std::ffi::c_void; +#[cfg(has_std__ffi__c_char)] use std::ffi::{c_char, c_int};
@@ -19,6 +21,8 @@ pub struct libgit_config_set { }extern "C" { +pub fn free (ptr: *mut c_void ); +pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ;
t/Makefile +7 -2
@@ -178,12 +178,17 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) -.PHONY: libgit-sys-test +.PHONY: libgit-sys-test libgit-rs-test libgit-sys-test: $(QUIET)(\ cd ../contrib/libgit-sys && \ cargo test \ ) +libgit-rs-test: + $(QUIET)(\ + cd ../contrib/libgit-rs && \ + cargo test \ + ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys-test +all:: libgit-sys-test libgit-rs-test endif
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
Re: [PATCH v7 4/4] libgit: add higher-level libgit crate
Quoted 6 lines · Josh Steadmon
-.PHONY: libgit-sys
+.PHONY: libgit-sys libgit-rs
libgit-sys:Makefile +0
-0$(QUIET)(\ cd contrib/libgit-sys && \ cargo build \
Makefile build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) · line 3923
Quoted 10 lines
Makefile +6
-1) +libgit-rs: + $(QUIET)(\ + cd contrib/libgit-rs && \ + cargo build \ + ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys +all:: libgit-sys libgit-rs endif
I somehow would have expected this part of the patch to do
libgit-sys libgit-rs: $(QUIET)( \ cd contrib/$@ && cargo build \ )
but the above longhand is fine.
contrib/libgit-rs/src/config.rs line 52
Quoted 13 lines
contrib/libgit-rs/src/config.rs new file +13
-0+/// Load the value for the given key and attempt to parse it as an i32. Dies with a fatal error +/// if the value cannot be parsed. Returns None if the key is not present. +pub fn get_int (&mut self, key: &str ) ->Option <i32 > { +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 valas *mut c_int ) !=0 { +return None ; + } + } + +Some (val.into ()) + }
Nice.
I was wondering why libgit_configset_get_int() in [3/4] does not do better than just wrapping the raw C interface, which returns the error/success status separately from the value we parsed. With this higher-layer wrapper around it, the interface becomes a bit more like a higher-level language.
Thanks, will queue.
Re: [PATCH v7 4/4] libgit: add higher-level libgit crate
Quoted 21 lines · Junio C Hamano
Quoted 6 lines · Josh Steadmon
-.PHONY: libgit-sys
+.PHONY: libgit-sys libgit-rs
libgit-sys:Makefile +0
-0$(QUIET)(\ cd contrib/libgit-sys && \ cargo build \Makefile build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) · line 3923
Quoted 10 lines
Makefile +6
-1) +libgit-rs: + $(QUIET)(\ + cd contrib/libgit-rs && \ + cargo build \ + ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys +all:: libgit-sys libgit-rs endifI somehow would have expected this part of the patch to do
Quoted 6 lines
libgit-sys libgit-rs: $(QUIET)( \ cd contrib/$@ && cargo build \ )but the above longhand is fine.
Fixed since I'm sending out a V8 for Phillip's feedback anyway. Thanks.
Quoted 23 lines
contrib/libgit-rs/src/config.rs line 52
Quoted 13 lines
contrib/libgit-rs/src/config.rs new file +13
-0+/// Load the value for the given key and attempt to parse it as an i32. Dies with a fatal error +/// if the value cannot be parsed. Returns None if the key is not present. +pub fn get_int (&mut self, key: &str ) ->Option <i32 > { +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 valas *mut c_int ) !=0 { +return None ; + } + } + +Some (val.into ()) + }Nice.
I was wondering why
libgit_configset_get_int()in [3/4] does not do better than just wrapping the raw C interface, which returns the error/success status separately from the value we parsed. With this higher-layer wrapper around it, the interface becomes a bit more like a higher-level language.Thanks, will queue.
Re: [PATCH v7 4/4] libgit: add higher-level libgit crate
Quoted 10 lines · Josh Steadmon
Quoted 8 lines
I somehow would have expected this part of the patch to do
libgit-sys libgit-rs: $(QUIET)( \ cd contrib/$@ && cargo build \ )but the above longhand is fine.
Fixed since I'm sending out a V8 for Phillip's feedback anyway. Thanks.
It would be a "fix" only if we anticipate that we will add in the future more Rust things to contrib/ and all of them would follow the same pattern. Otherwise, it does not really matter, and as I said, what you posted is just fine.
Thanks.
v8 cover Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonThis series provides two small Rust wrapper libraries around parts of
Git: "libgit-sys", which exposes a few functions from libgit.a, and "libgit", which provides a more Rust-friendly interface to some of those functions. In addition to included unit tests, at $DAYJOB we have tested building JJ[1] with our library and used it to replace some of the libgit2-rs uses.
[1] https://github.com/jj-vcs/jj
There is known NEEDSWORK, but I feel that they can be addressed in follow-up changes, rather than in this series. If you feel otherwise, please let me know:
* Investigate alternative methods of managing symbol visibility & renaming.
* Figure out symbol versioning
Changes in V8:
* Define a private libgit_config_set struct to avoid excessive casting in public_symbol_export.c.
* Style fixes: merge some Makefile rules, limit rule line length by defining intermediate variables, add initial empty comment line, add linebreaks in function definitions.
Changes in V7:
* Moved the ConfigSet implementation in libgit-rs to a config module.
* Added doc comments for ConfigSet and its methods.
* Fix meson builds by adding new object files to libgit_sources
* Moved INCLUDE_LIBGIT_RS Makefile changes earlier in the series, so that we can make it optional to compile some of the libgitpub sources. Squashed V6 patch 5/5 into this series' patch 4/4.
* Don't publicly export FFI types in libgit-rs.
* Removed extraneous -r argument to $(RM) in the clean rules.
* Added TODO reminder in Cargo.toml about removing Cargo.lock once we hit a certain minimum supported Rust version.
* Style cleanup in public_symbol_export.c
Changes in V6:
* Rebased onto current master, since V5 was several months old.
* Move libgit-sys out of libgit-rs; while this sort of nesting is common in Rust crates with standalone repositories, it doesn't make as much sense when they're contained in the larger Git project's repo.
* Standardize the naming of some of the Makefile targets to always include a dash in the "-rs" or "-sys" suffixes.
* Clean up READMEs and crate descriptions in preparation for uploading to crates.io.
Changes in V5:
* When building with INCLUDE_LIBGIT_RS defined, add "-fvisibility=hidden" to CFLAGS. This allows us to manage symbol visibility in libgitpub.a without causing make all to rebuild from scratch due to changing CFLAGS.
* Avoid using c_int in the higher-level Rust API.
* Remove libgitpub.a and intermediate files with make clean.
Changes in V4:
* Drop V3 patch #3, which added wrappers around repository initialization and config access. These are not well-libified, and they are not necessary for JJ's proof-of-concept use case, so let's avoid exporting them for now.
* Set a minimum supported Rust version of 1.63. Autodetect whether our Rust version has c_int and c_char types; if not, define them ourselves.
* When building libgitpub.a via build.rs, set DEVELOPER=1 to catch additional errors at build time.
* In build.rs, use the make_cmd crate to portable select the correct invocation of GNU Make.
* Follow naming standards for _alloc() and _free() functions.
* Use String instead of CString in higher-level API.
* Move libgit_configset_alloc() and libgit_configset_free() out of upstream Git, to the libgitpub shim library.
* In libgitpub, initialize libgit_config_set structs in the _alloc() function rather than with a separate _init() function.
* Remove unnecessary comments in libgit-sys showing where the wrapped functions were originally defined.
* Fix clippy lint: don't reborrow configfile path references.
* Various typo fixes and cargo fmt fixes.
Changes in V3:
* Renamed cgit-rs to libgit-rs and cgit-sys to libgit-sys
* Makefile cleanup, particularly adding config.mak options that developers can set to run Rust builds and tests by default (Patch 6)
* Provide testdata configs for unit tests
* ConfigSet API now uses &Path instead of &str -- more ergonomic for Rust users to pass in and errors out if the path string isn't UTF-8
* Fixed unresolved dependency on libz in Cargo.toml
Calvin Wan (1):
libgit: add higher-level libgit crate
Josh Steadmon (3):
common-main: split init and exit code into new files
libgit-sys: introduce Rust wrapper for libgit.a
libgit-sys: also export some config_set functions
.gitignore | 2 + Makefile | 49 ++++++++++ common-exit.c | 26 ++++++ common-init.c | 63 +++++++++++++ common-init.h | 6 ++ common-main.c | 83 +---------------- contrib/libgit-rs/Cargo.lock | 77 ++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 ++++ contrib/libgit-rs/README.md | 13 +++ contrib/libgit-rs/build.rs | 4 + contrib/libgit-rs/src/config.rs | 106 ++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/Cargo.lock | 69 ++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 ++++ contrib/libgit-sys/README.md | 4 + contrib/libgit-sys/build.rs | 35 +++++++ contrib/libgit-sys/public_symbol_export.c | 59 ++++++++++++ contrib/libgit-sys/public_symbol_export.h | 18 ++++ contrib/libgit-sys/src/lib.rs | 79 ++++++++++++++++ meson.build | 2 + t/Makefile | 15 +++ 24 files changed, 672 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/config.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3 create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644 contrib/libgit-sys/Cargo.toml create mode 100644 contrib/libgit-sys/README.md create mode 100644 contrib/libgit-sys/build.rs create mode 100644 contrib/libgit-sys/public_symbol_export.c create mode 100644 contrib/libgit-sys/public_symbol_export.h create mode 100644 contrib/libgit-sys/src/lib.rs
Range-diff against v7:
1: cd0cb9aa04 = 1: cd0cb9aa04 common-main: split init and exit code into new files
2: f1502b8590 ! 2: 3588a3c3fc libgit-sys: introduce Rust wrapper for libgit.a
@@ Makefile: $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GIT
+all:: libgit-sys
+endif
+
-+contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a
++LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o
++LIBGIT_PUB_OBJS += libgit.a
++LIBGIT_PUB_OBJS += reftable/libreftable.a
++LIBGIT_PUB_OBJS += xdiff/lib.a
++
++LIBGIT_PARTIAL_EXPORT = contrib/libgit-sys/partial_symbol_export.o
++
++LIBGIT_HIDDEN_EXPORT = contrib/libgit-sys/hidden_symbol_export.o
++
++$(LIBGIT_PARTIAL_EXPORT): $(LIBGIT_PUB_OBJS)
+ $(LD) -r $^ -o $@
+
-+contrib/libgit-sys/hidden_symbol_export.o: contrib/libgit-sys/partial_symbol_export.o
++$(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)
+ $(OBJCOPY) --localize-hidden $^ $@
+
-+contrib/libgit-sys/libgitpub.a: contrib/libgit-sys/hidden_symbol_export.o
++contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)
+ $(AR) $(ARFLAGS) $@ $^
## contrib/libgit-sys/Cargo.lock (new) ##
@@ contrib/libgit-sys/build.rs (new)
## contrib/libgit-sys/public_symbol_export.c (new) ##
@@
-+/* Shim to publicly export Git symbols. These must be renamed so that the
++/*
++ * 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
+ * avoids conflicts with other libraries such as libgit2.
+ */
3: d67d3648d1 ! 3: f4452fffe6 libgit-sys: also export some config_set functions
@@ contrib/libgit-sys/public_symbol_export.c
#pragma GCC visibility push(default)
++struct libgit_config_set {
++ struct config_set cs;
++};
++
+struct libgit_config_set *libgit_configset_alloc(void)
+{
-+ struct config_set *cs = xmalloc(sizeof(struct config_set));
-+ git_configset_init(cs);
-+ return (struct libgit_config_set *) cs;
++ struct libgit_config_set *cs =
++ xmalloc(sizeof(struct libgit_config_set));
++ git_configset_init(&cs->cs);
++ return cs;
+}
+
+void libgit_configset_free(struct libgit_config_set *cs)
+{
-+ git_configset_clear((struct config_set *) cs);
-+ free((struct config_set *) cs);
++ git_configset_clear(&cs->cs);
++ free(&cs->cs);
+}
+
+int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename)
+{
-+ return git_configset_add_file((struct config_set *) cs, filename);
++ return git_configset_add_file(&cs->cs, filename);
+}
+
-+int libgit_configset_get_int(struct libgit_config_set *cs, const char *key, int *dest)
++int libgit_configset_get_int(struct libgit_config_set *cs, const char *key,
++ int *dest)
+{
-+ return git_configset_get_int((struct config_set *) cs, key, dest);
++ return git_configset_get_int(&cs->cs, key, dest);
+}
+
-+int libgit_configset_get_string(struct libgit_config_set *cs, const char *key, char **dest)
++int libgit_configset_get_string(struct libgit_config_set *cs, const char *key,
++ char **dest)
+{
-+ return git_configset_get_string((struct config_set *) cs, key, dest);
++ return git_configset_get_string(&cs->cs, key, dest);
+}
+
const char *libgit_user_agent(void)
4: 88425bb0b1 ! 4: ada9fc0a13 libgit: add higher-level libgit crate
@@ Makefile: build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
$(MAKE) -C t/ unit-tests
-.PHONY: libgit-sys
+-libgit-sys:
+.PHONY: libgit-sys libgit-rs
- libgit-sys:
++libgit-sys libgit-rs:
$(QUIET)(\
- cd contrib/libgit-sys && \
+- cd contrib/libgit-sys && \
++ cd contrib/$@ && \
cargo build \
)
-+libgit-rs:
-+ $(QUIET)(\
-+ cd contrib/libgit-rs && \
-+ cargo build \
-+ )
ifdef INCLUDE_LIBGIT_RS
-all:: libgit-sys
+all:: libgit-sys libgit-rs
endif
- contrib/libgit-sys/partial_symbol_export.o: contrib/libgit-sys/public_symbol_export.o libgit.a reftable/libreftable.a xdiff/lib.a
+ LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o
## contrib/libgit-rs/Cargo.lock (new) ##
@@base-commit: 757161efcca150a9a96b312d9e780a071e601a03
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
PATCH v8 1/4 common-main: split init and exit code into new files
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/[email protected]/
[2] https://lore.kernel.org/git/[email protected]/
--- Makefile | 2 ++ common-exit.c | 26 ++++++++++++++++ common-init.c | 63 ++++++++++++++++++++++++++++++++++++++ common-init.h | 6 ++++ common-main.c | 83 ++------------------------------------------------- meson.build | 2 ++ 6 files changed, 101 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h
Makefile +2 -0
@@ -981,6 +981,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
common-exit.c new file +26 -0
@@ -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; +}
common-init.c new file +63 -0
63 lines not on this page · raw message
common-init.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef COMMON_INIT_H +#define COMMON_INIT_H + +void init_git (const char **argv); + +#endif /* COMMON_INIT_H */
common-main.c +2 -81
94 lines not on this page · raw message
meson.build +2 -0
@@ -245,6 +245,8 @@ libgit_sources = [ 'commit-graph.c', 'commit-reach.c', 'commit.c', + 'common-exit.c', + 'common-init.c', 'compat/nonblock.c', 'compat/obstack.c', 'compat/terminal.c',
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
PATCH v8 2/4 libgit-sys: introduce Rust wrapper for libgit.a
In reply to Josh SteadmonIntroduce libgit-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 containing a more Rust-friendly interface will be added at contrib/libgit-rs.
Symbols in libgit 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/libgit-rs/libgit-sys/libgitpub.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.
--- .gitignore | 1 + Makefile | 47 +++++++++++++++ contrib/libgit-sys/Cargo.lock | 69 +++++++++++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 +++++++ contrib/libgit-sys/README.md | 4 ++ contrib/libgit-sys/build.rs | 35 ++++++++++++ contrib/libgit-sys/public_symbol_export.c | 23 ++++++++ contrib/libgit-sys/public_symbol_export.h | 8 +++ contrib/libgit-sys/src/lib.rs | 46 +++++++++++++++ t/Makefile | 10 ++++ 10 files changed, 262 insertions(+) create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644 contrib/libgit-sys/Cargo.toml create mode 100644 contrib/libgit-sys/README.md create mode 100644 contrib/libgit-sys/build.rs create mode 100644 contrib/libgit-sys/public_symbol_export.c create mode 100644 contrib/libgit-sys/public_symbol_export.h create mode 100644 contrib/libgit-sys/src/lib.rs
.gitignore +1 -0
@@ -250,3 +250,4 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-sys/target
Makefile +47 -0
80 lines not on this page · raw message
contrib/libgit-sys/Cargo.lock new file +69 -0
69 lines not on this page · raw message
contrib/libgit-sys/Cargo.toml new file +19 -0
@@ -0,0 +1,19 @@ +[package] +name = "libgit-sys" +version = "0.1.0" +edition = "2021" +build = "build.rs" +links = "gitpub" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/[email protected]/ +description = "Native bindings to a portion of libgit" + +[lib] +path = "src/lib.rs" + +[dependencies] +libz-sys = "1.1.19" + +[build-dependencies] +autocfg = "1.4.0" +make-cmd = "0.1.0"
contrib/libgit-sys/README.md new file +4 -0
@@ -0,0 +1,4 @@ +# libgit-sys + +A small proof-of-concept crate showing how to provide a Rust FFI to Git +internals.
contrib/libgit-sys/build.rs new file +35 -0
@@ -0,0 +1,35 @@ +use std::env; +use std::path::PathBuf ; + +pub fn main () -> std::io::Result <()> { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); + +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 = make_cmd::gnu_make () + .env ("DEVELOPER" ,"1" ) + .env_remove ("PROFILE" ) + .current_dir (git_root.clone ()) + .args ([ +"INCLUDE_LIBGIT_RS=YesPlease" , +"contrib/libgit-sys/libgitpub.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 ("libgitpub.a" ), dst.join ("libgitpub.a" ))?; +println! ("cargo:rustc-link-search=native={}" , dst.display ()); +println! ("cargo:rustc-link-lib=gitpub" ); +println! ("cargo:rerun-if-changed={}" , git_root.display ()); + +Ok (()) +}
contrib/libgit-sys/public_symbol_export.c new file +23 -0
@@ -0,0 +1,23 @@ +/* +* 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 +* avoids conflicts with other libraries such as libgit2. +*/ + +#include "git-compat-util.h" +#include "contrib/libgit-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
contrib/libgit-sys/public_symbol_export.h new file +8 -0
@@ -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 */
contrib/libgit-sys/src/lib.rs new file +46 -0
46 lines not on this page · raw message
t/Makefile +10 -0
@@ -177,3 +177,13 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) + +.PHONY: libgit-sys-test +libgit-sys-test: + $(QUIET)(\ + cd ../contrib/libgit-sys && \ + cargo test \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys-test +endif
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
Re: [PATCH v8 2/4] libgit-sys: introduce Rust wrapper for libgit.a
Quoted 15 lines · Josh Steadmon
Makefile +3
-0@@ -416,6 +416,9 @@ include shared.mak # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test # programs in oss-fuzz/. # +# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and +# test the Rust crate in contrib/libgit-sys. +# # === Optional library: libintl === # # Define NO_GETTEXT if you don't want Git output to be translated.
Makefile CURL_CONFIG = curl-config · line 666
Quoted 7 lines
Makefile +2
-0@@ -657,6 +660,8 @@ CURL_CONFIG = curl-config GCOV = gcov STRIP = strip SPATCH = spatch +LD = ld +OBJCOPY = objcopy export TCL_PATH TCLTK_PATH
Good.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3923
Quoted 4 lines
Makefile +4
-0+LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o +LIBGIT_PUB_OBJS += libgit.a +LIBGIT_PUB_OBJS += reftable/libreftable.a +LIBGIT_PUB_OBJS += xdiff/lib.a
This is a fairly minor point, but if we look at the places where OBJECTS, PROGRAMS, and friends are prepared in the Makefile, they all start with empty, i.e.
LIBGIT_PUB_OBJS =
at a fairly early place in the file, and then appends real contents to the symbol with += assignment. It probably makes sense to follow suit, although the result would be the same.
Other than that, nothing jumped at me as fishy. Nicely done.
Thanks. Will replace.
Re: [PATCH v8 2/4] libgit-sys: introduce Rust wrapper for libgit.a
Quoted 38 lines · Junio C Hamano
Quoted 15 lines · Josh Steadmon
Makefile +3
-0@@ -416,6 +416,9 @@ include shared.mak # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test # programs in oss-fuzz/. # +# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and +# test the Rust crate in contrib/libgit-sys. +# # === Optional library: libintl === # # Define NO_GETTEXT if you don't want Git output to be translated.Makefile CURL_CONFIG = curl-config · line 666
Quoted 7 lines
Makefile +2
-0@@ -657,6 +660,8 @@ CURL_CONFIG = curl-config GCOV = gcov STRIP = strip SPATCH = spatch +LD = ld +OBJCOPY = objcopy export TCL_PATH TCLTK_PATHGood.
Makefile $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- · line 3923
Quoted 4 lines
Makefile +4
-0+LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o +LIBGIT_PUB_OBJS += libgit.a +LIBGIT_PUB_OBJS += reftable/libreftable.a +LIBGIT_PUB_OBJS += xdiff/lib.aThis is a fairly minor point, but if we look at the places where OBJECTS, PROGRAMS, and friends are prepared in the
Makefile, they all start with empty, i.e.
LIBGIT_PUB_OBJS=
Quoted 7 lines
at a fairly early place in the file, and then appends real contents to the symbol with += assignment. It probably makes sense to follow suit, although the result would be the same.
Other than that, nothing jumped at me as fishy. Nicely done.
Thanks. Will replace.
Ack, will send a V9 soon with this & a fix for Phillip's feedback. Thanks.
PATCH v8 3/4 libgit-sys: also export some config_set functions
In reply to Josh SteadmonIn preparation for implementing a higher-level Rust API for accessing Git configs, export some of the upstream configset API via libgitpub and libgit-sys. Since this will be exercised as part of the higher-level API in the next commit, no tests have been added for libgit-sys.
While we're at it, add git_configset_alloc() and git_configset_free() functions in libgitpub 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.
--- contrib/libgit-sys/public_symbol_export.c | 36 +++++++++++++++++++++++ contrib/libgit-sys/public_symbol_export.h | 10 +++++++ contrib/libgit-sys/src/lib.rs | 31 ++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-)
contrib/libgit-sys/public_symbol_export.c +36 -0
@@ -5,11 +5,47 @@*/ #include "git-compat-util.h" +#include "config.h" #include "contrib/libgit-sys/public_symbol_export.h" #include "version.h" #pragma GCC visibility push(default) +struct libgit_config_set { +struct config_set cs; +}; + +struct libgit_config_set *libgit_configset_alloc (void ) +{ +struct libgit_config_set *cs = +xmalloc (sizeof (struct libgit_config_set )); +git_configset_init (&cs->cs); +return cs; +} + +void libgit_configset_free (struct libgit_config_set *cs) +{ +git_configset_clear (&cs->cs); +free (&cs->cs); +} + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename) +{ +return git_configset_add_file (&cs->cs, filename); +} + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key, +int *dest) +{ +return git_configset_get_int (&cs->cs, key, dest); +} + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key, +char **dest) +{ +return git_configset_get_string (&cs->cs, key, dest); +} +const char *libgit_user_agent (void ) {return git_user_agent ();
contrib/libgit-sys/public_symbol_export.h +10 -0
@@ -1,6 +1,16 @@#ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +struct libgit_config_set *libgit_configset_alloc (void ); + +void libgit_configset_free (struct libgit_config_set *cs); + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename); + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest); + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest); +const char *libgit_user_agent (void );const char *libgit_user_agent_sanitized (void );
contrib/libgit-sys/src/lib.rs +30 -1
@@ -1,15 +1,44 @@#[cfg(has_std__ffi__c_char)] -use std::ffi::c_char; +use std::ffi::{c_char, c_int};#[cfg(not(has_std__ffi__c_char))] #[allow(non_camel_case_types)] pub type c_char =i8 ; +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ; +extern crate libz_sys; +#[allow(non_camel_case_types)] +#[repr( C )] +pub struct libgit_config_set { + _data: [u8 ;0 ], + _marker: core::marker::PhantomData <(*mut u8 , core::marker::PhantomPinned )>, +} +extern "C" {pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ; + +pub fn libgit_configset_alloc () -> *mut libgit_config_set ; +pub fn libgit_configset_free (cs: *mut libgit_config_set ); + +pub fn libgit_configset_add_file (cs: *mut libgit_config_set , filename: *const c_char ) ->c_int ; + +pub fn libgit_configset_get_int ( + cs: *mut libgit_config_set , + key: *const c_char , + int: *mut c_int , + ) ->c_int ; + +pub fn libgit_configset_get_string ( + cs: *mut libgit_config_set , + key: *const c_char , + dest: *mut *mut c_char , + ) ->c_int ; + }#[cfg(test)]
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
PATCH v8 4/4 libgit: add higher-level libgit crate
In reply to Josh SteadmonFrom: Calvin Wan <[email protected]>
The C functions exported by libgit-sys do not provide an idiomatic Rust interface. To make it easier to use these functions via Rust, add a higher-level "libgit" crate, that wraps the lower-level configset API with an interface that is more Rust-y.
This combination of $X and $X-sys crates is a common pattern for FFI in Rust, as documented in "The Cargo Book" [1].
[1] https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
--- .gitignore | 1 + Makefile | 12 ++-- contrib/libgit-rs/Cargo.lock | 77 +++++++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 +++++ contrib/libgit-rs/README.md | 13 ++++ contrib/libgit-rs/build.rs | 4 ++ contrib/libgit-rs/src/config.rs | 106 +++++++++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/src/lib.rs | 4 ++ t/Makefile | 9 ++- 13 files changed, 242 insertions(+), 8 deletions(-) create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/config.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3
.gitignore +1 -0
@@ -250,4 +250,5 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-rs/target /contrib/libgit-sys/target
Makefile +6 -6
@@ -417,7 +417,7 @@ include shared.mak # programs in oss-fuzz/. # # Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and -# test the Rust crate in contrib/libgit-sys. +# test the Rust crates in contrib/libgit-sys and contrib/libgit-rs. # # === Optional library: libintl === #
@@ -3741,7 +3741,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/libgit-sys/target + $(RM) -r contrib/libgit-sys/target contrib/libgit-rs/target $(RM) contrib/libgit-sys/partial_symbol_export.o $(RM) contrib/libgit-sys/hidden_symbol_export.o $(RM) contrib/libgit-sys/libgitpub.a
@@ -3907,14 +3907,14 @@ build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests -.PHONY: libgit-sys -libgit-sys: +.PHONY: libgit-sys libgit-rs +libgit-sys libgit-rs: $(QUIET)(\ - cd contrib/libgit-sys && \ + cd contrib/$@ && \ cargo build \ ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys +all:: libgit-sys libgit-rs endif LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o
contrib/libgit-rs/Cargo.lock new file +77 -0
77 lines not on this page · raw message
contrib/libgit-rs/Cargo.toml new file +17 -0
@@ -0,0 +1,17 @@ +[package] +name = "libgit" +version = "0.1.0" +edition = "2021" +build = "build.rs" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/[email protected]/ + + +[lib] +path = "src/lib.rs" + +[dependencies] +libgit-sys = { version = "0.1.0", path = "../libgit-sys" } + +[build-dependencies] +autocfg = "1.4.0"
contrib/libgit-rs/README.md new file +13 -0
@@ -0,0 +1,13 @@ +# libgit-rs + +Proof-of-concept Git bindings for Rust. + +```toml +[dependencies] +libgit = "0.1.0" +``` + +## Rust version requirements + +libgit-rs should support Rust versions at least as old as the version included +in Debian stable (currently 1.63).
contrib/libgit-rs/build.rs new file +4 -0
@@ -0,0 +1,4 @@ +pub fn main () { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); +}
contrib/libgit-rs/src/config.rs new file +106 -0
106 lines not on this page · raw message
contrib/libgit-rs/src/lib.rs new file +1 -0
@@ -0,0 +1 @@ +pub mod config;
contrib/libgit-rs/testdata/config1 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 1
contrib/libgit-rs/testdata/config2 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventTarget = 1
contrib/libgit-rs/testdata/config3 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 3
contrib/libgit-sys/src/lib.rs +4 -0
@@ -1,3 +1,5 @@ +use std::ffi::c_void; +#[cfg(has_std__ffi__c_char)] use std::ffi::{c_char, c_int};
@@ -19,6 +21,8 @@ pub struct libgit_config_set { }extern "C" { +pub fn free (ptr: *mut c_void ); +pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ;
t/Makefile +7 -2
@@ -178,12 +178,17 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) -.PHONY: libgit-sys-test +.PHONY: libgit-sys-test libgit-rs-test libgit-sys-test: $(QUIET)(\ cd ../contrib/libgit-sys && \ cargo test \ ) +libgit-rs-test: + $(QUIET)(\ + cd ../contrib/libgit-rs && \ + cargo test \ + ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys-test +all:: libgit-sys-test libgit-rs-test endif
Signature · 1 line
2.48.1.262.g85cc9f2d1e-goog
Re: [PATCH v8 0/4] Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonHi Josh
On 28/01/2025 22:01, Josh Steadmon wrote:
Thanks for re-rolling, the range-diff looks good to me apart from
Quoted 6 lines
+void libgit_configset_free(struct libgit_config_set *cs)
+{
-+ git_configset_clear((struct config_set *) cs);
-+ free((struct config_set *) cs);
++ git_configset_clear(&cs->cs);
++ free(&cs->cs);Which I think should be "free(cs)". In practice it does not matter because we pass the same value to free() but it seems a bit odd to pass the address of the first member of the struct rather than the address of the struct itself.
I'm looking forward to seeing this merged soon
Best Wishes
Phillip
Re: [PATCH v8 0/4] Introduce libgit-rs, a Rust wrapper around libgit.a
Quoted 13 lines · Phillip Wood
Hi Josh
On 28/01/2025 22:01, Josh Steadmon wrote:
Thanks for re-rolling, the range-diff looks good to me apart from
Quoted 6 lines
+void libgit_configset_free(struct libgit_config_set *cs) +{ -+ git_configset_clear((struct config_set *) cs); -+ free((struct config_set *) cs); ++ git_configset_clear(&cs->cs); ++ free(&cs->cs);
Quoted 4 lines
Which I think should be "free(cs)". In practice it does not matter because we pass the same value to
free()but it seems a bit odd to pass the address of the first member of the struct rather than the address of the struct itself.
Yep sorry, got a bit careless with search-and-replace. Thanks for the catch!
Quoted 6 lines
I'm looking forward to seeing this merged soon
Best Wishes
Phillip
v9 cover Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonThis series provides two small Rust wrapper libraries around parts of
Git: "libgit-sys", which exposes a few functions from libgit.a, and "libgit", which provides a more Rust-friendly interface to some of those functions. In addition to included unit tests, at $DAYJOB we have tested building JJ[1] with our library and used it to replace some of the libgit2-rs uses.
[1] https://github.com/jj-vcs/jj
There is known NEEDSWORK, but I feel that they can be addressed in follow-up changes, rather than in this series. If you feel otherwise, please let me know:
* Investigate alternative methods of managing symbol visibility & renaming.
* Figure out symbol versioning
Changes in V9:
* Properly initialize Makefile var LIBGIT_PUB_OBJS.
* Pass the correct pointer to free in libgit_configset_free().
Changes in V8:
* Define a private libgit_config_set struct to avoid excessive casting in public_symbol_export.c.
* Style fixes: merge some Makefile rules, limit rule line length by defining intermediate variables, add initial empty comment line, add linebreaks in function definitions.
Changes in V7:
* Moved the ConfigSet implementation in libgit-rs to a config module.
* Added doc comments for ConfigSet and its methods.
* Fix meson builds by adding new object files to libgit_sources
* Moved INCLUDE_LIBGIT_RS Makefile changes earlier in the series, so that we can make it optional to compile some of the libgitpub sources. Squashed V6 patch 5/5 into this series' patch 4/4.
* Don't publicly export FFI types in libgit-rs.
* Removed extraneous -r argument to $(RM) in the clean rules.
* Added TODO reminder in Cargo.toml about removing Cargo.lock once we hit a certain minimum supported Rust version.
* Style cleanup in public_symbol_export.c
Changes in V6:
* Rebased onto current master, since V5 was several months old.
* Move libgit-sys out of libgit-rs; while this sort of nesting is common in Rust crates with standalone repositories, it doesn't make as much sense when they're contained in the larger Git project's repo.
* Standardize the naming of some of the Makefile targets to always include a dash in the "-rs" or "-sys" suffixes.
* Clean up READMEs and crate descriptions in preparation for uploading to crates.io.
Changes in V5:
* When building with INCLUDE_LIBGIT_RS defined, add "-fvisibility=hidden" to CFLAGS. This allows us to manage symbol visibility in libgitpub.a without causing make all to rebuild from scratch due to changing CFLAGS.
* Avoid using c_int in the higher-level Rust API.
* Remove libgitpub.a and intermediate files with make clean.
Changes in V4:
* Drop V3 patch #3, which added wrappers around repository initialization and config access. These are not well-libified, and they are not necessary for JJ's proof-of-concept use case, so let's avoid exporting them for now.
* Set a minimum supported Rust version of 1.63. Autodetect whether our Rust version has c_int and c_char types; if not, define them ourselves.
* When building libgitpub.a via build.rs, set DEVELOPER=1 to catch additional errors at build time.
* In build.rs, use the make_cmd crate to portable select the correct invocation of GNU Make.
* Follow naming standards for _alloc() and _free() functions.
* Use String instead of CString in higher-level API.
* Move libgit_configset_alloc() and libgit_configset_free() out of upstream Git, to the libgitpub shim library.
* In libgitpub, initialize libgit_config_set structs in the _alloc() function rather than with a separate _init() function.
* Remove unnecessary comments in libgit-sys showing where the wrapped functions were originally defined.
* Fix clippy lint: don't reborrow configfile path references.
* Various typo fixes and cargo fmt fixes.
Changes in V3:
* Renamed cgit-rs to libgit-rs and cgit-sys to libgit-sys
* Makefile cleanup, particularly adding config.mak options that developers can set to run Rust builds and tests by default (Patch 6)
* Provide testdata configs for unit tests
* ConfigSet API now uses &Path instead of &str -- more ergonomic for Rust users to pass in and errors out if the path string isn't UTF-8
* Fixed unresolved dependency on libz in Cargo.toml
Calvin Wan (1):
libgit: add higher-level libgit crate
Josh Steadmon (3):
common-main: split init and exit code into new files
libgit-sys: introduce Rust wrapper for libgit.a
libgit-sys: also export some config_set functions
.gitignore | 2 + Makefile | 50 ++++++++++ common-exit.c | 26 ++++++ common-init.c | 63 +++++++++++++ common-init.h | 6 ++ common-main.c | 83 +---------------- contrib/libgit-rs/Cargo.lock | 77 ++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 ++++ contrib/libgit-rs/README.md | 13 +++ contrib/libgit-rs/build.rs | 4 + contrib/libgit-rs/src/config.rs | 106 ++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/Cargo.lock | 69 ++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 ++++ contrib/libgit-sys/README.md | 4 + contrib/libgit-sys/build.rs | 35 +++++++ contrib/libgit-sys/public_symbol_export.c | 59 ++++++++++++ contrib/libgit-sys/public_symbol_export.h | 18 ++++ contrib/libgit-sys/src/lib.rs | 79 ++++++++++++++++ meson.build | 2 + t/Makefile | 15 +++ 24 files changed, 673 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/config.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3 create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644 contrib/libgit-sys/Cargo.toml create mode 100644 contrib/libgit-sys/README.md create mode 100644 contrib/libgit-sys/build.rs create mode 100644 contrib/libgit-sys/public_symbol_export.c create mode 100644 contrib/libgit-sys/public_symbol_export.h create mode 100644 contrib/libgit-sys/src/lib.rs
Range-diff against v8:
1: cd0cb9aa04 = 1: cd0cb9aa04 common-main: split init and exit code into new files
2: 3588a3c3fc ! 2: 8793ff64a7 libgit-sys: introduce Rust wrapper for libgit.a
@@ Makefile: $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GIT
+all:: libgit-sys
+endif
+
-+LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o
++LIBGIT_PUB_OBJS =
++LIBGIT_PUB_OBJS += contrib/libgit-sys/public_symbol_export.o
+LIBGIT_PUB_OBJS += libgit.a
+LIBGIT_PUB_OBJS += reftable/libreftable.a
+LIBGIT_PUB_OBJS += xdiff/lib.a
3: f4452fffe6 ! 3: ab32bd1d07 libgit-sys: also export some config_set functions
@@ contrib/libgit-sys/public_symbol_export.c
+void libgit_configset_free(struct libgit_config_set *cs)
+{
+ git_configset_clear(&cs->cs);
-+ free(&cs->cs);
++ free(cs);
+}
+
+int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename)4: ada9fc0a13 ! 4: 1bf8c5392c libgit: add higher-level libgit crate
@@ Makefile: build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
+all:: libgit-sys libgit-rs
endif
- LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o
+ LIBGIT_PUB_OBJS =
## contrib/libgit-rs/Cargo.lock (new) ##
@@
base-commit: 757161efcca150a9a96b312d9e780a071e601a03
Signature · 1 line
2.48.1.362.g079036d154-goog
PATCH v9 1/4 common-main: split init and exit code into new files
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/[email protected]/
[2] https://lore.kernel.org/git/[email protected]/
--- Makefile | 2 ++ common-exit.c | 26 ++++++++++++++++ common-init.c | 63 ++++++++++++++++++++++++++++++++++++++ common-init.h | 6 ++++ common-main.c | 83 ++------------------------------------------------- meson.build | 2 ++ 6 files changed, 101 insertions(+), 81 deletions(-) create mode 100644 common-exit.c create mode 100644 common-init.c create mode 100644 common-init.h
Makefile +2 -0
@@ -981,6 +981,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
common-exit.c new file +26 -0
@@ -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; +}
common-init.c new file +63 -0
63 lines not on this page · raw message
common-init.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef COMMON_INIT_H +#define COMMON_INIT_H + +void init_git (const char **argv); + +#endif /* COMMON_INIT_H */
common-main.c +2 -81
94 lines not on this page · raw message
meson.build +2 -0
@@ -245,6 +245,8 @@ libgit_sources = [ 'commit-graph.c', 'commit-reach.c', 'commit.c', + 'common-exit.c', + 'common-init.c', 'compat/nonblock.c', 'compat/obstack.c', 'compat/terminal.c',
Signature · 1 line
2.48.1.362.g079036d154-goog
PATCH v9 2/4 libgit-sys: introduce Rust wrapper for libgit.a
In reply to Josh SteadmonIntroduce libgit-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 containing a more Rust-friendly interface will be added at contrib/libgit-rs.
Symbols in libgit 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/libgit-rs/libgit-sys/libgitpub.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.
--- .gitignore | 1 + Makefile | 48 ++++++++++++++++ contrib/libgit-sys/Cargo.lock | 69 +++++++++++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 +++++++ contrib/libgit-sys/README.md | 4 ++ contrib/libgit-sys/build.rs | 35 ++++++++++++ contrib/libgit-sys/public_symbol_export.c | 23 ++++++++ contrib/libgit-sys/public_symbol_export.h | 8 +++ contrib/libgit-sys/src/lib.rs | 46 +++++++++++++++ t/Makefile | 10 ++++ 10 files changed, 263 insertions(+) create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644 contrib/libgit-sys/Cargo.toml create mode 100644 contrib/libgit-sys/README.md create mode 100644 contrib/libgit-sys/build.rs create mode 100644 contrib/libgit-sys/public_symbol_export.c create mode 100644 contrib/libgit-sys/public_symbol_export.h create mode 100644 contrib/libgit-sys/src/lib.rs
.gitignore +1 -0
@@ -250,3 +250,4 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-sys/target
Makefile +48 -0
81 lines not on this page · raw message
contrib/libgit-sys/Cargo.lock new file +69 -0
69 lines not on this page · raw message
contrib/libgit-sys/Cargo.toml new file +19 -0
@@ -0,0 +1,19 @@ +[package] +name = "libgit-sys" +version = "0.1.0" +edition = "2021" +build = "build.rs" +links = "gitpub" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/[email protected]/ +description = "Native bindings to a portion of libgit" + +[lib] +path = "src/lib.rs" + +[dependencies] +libz-sys = "1.1.19" + +[build-dependencies] +autocfg = "1.4.0" +make-cmd = "0.1.0"
contrib/libgit-sys/README.md new file +4 -0
@@ -0,0 +1,4 @@ +# libgit-sys + +A small proof-of-concept crate showing how to provide a Rust FFI to Git +internals.
contrib/libgit-sys/build.rs new file +35 -0
@@ -0,0 +1,35 @@ +use std::env; +use std::path::PathBuf ; + +pub fn main () -> std::io::Result <()> { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); + +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 = make_cmd::gnu_make () + .env ("DEVELOPER" ,"1" ) + .env_remove ("PROFILE" ) + .current_dir (git_root.clone ()) + .args ([ +"INCLUDE_LIBGIT_RS=YesPlease" , +"contrib/libgit-sys/libgitpub.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 ("libgitpub.a" ), dst.join ("libgitpub.a" ))?; +println! ("cargo:rustc-link-search=native={}" , dst.display ()); +println! ("cargo:rustc-link-lib=gitpub" ); +println! ("cargo:rerun-if-changed={}" , git_root.display ()); + +Ok (()) +}
contrib/libgit-sys/public_symbol_export.c new file +23 -0
@@ -0,0 +1,23 @@ +/* +* 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 +* avoids conflicts with other libraries such as libgit2. +*/ + +#include "git-compat-util.h" +#include "contrib/libgit-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
contrib/libgit-sys/public_symbol_export.h new file +8 -0
@@ -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 */
contrib/libgit-sys/src/lib.rs new file +46 -0
46 lines not on this page · raw message
t/Makefile +10 -0
@@ -177,3 +177,13 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) + +.PHONY: libgit-sys-test +libgit-sys-test: + $(QUIET)(\ + cd ../contrib/libgit-sys && \ + cargo test \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys-test +endif
Signature · 1 line
2.48.1.362.g079036d154-goog
PATCH v9 3/4 libgit-sys: also export some config_set functions
In reply to Josh SteadmonIn preparation for implementing a higher-level Rust API for accessing Git configs, export some of the upstream configset API via libgitpub and libgit-sys. Since this will be exercised as part of the higher-level API in the next commit, no tests have been added for libgit-sys.
While we're at it, add git_configset_alloc() and git_configset_free() functions in libgitpub 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.
--- contrib/libgit-sys/public_symbol_export.c | 36 +++++++++++++++++++++++ contrib/libgit-sys/public_symbol_export.h | 10 +++++++ contrib/libgit-sys/src/lib.rs | 31 ++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-)
contrib/libgit-sys/public_symbol_export.c +36 -0
@@ -5,11 +5,47 @@*/ #include "git-compat-util.h" +#include "config.h" #include "contrib/libgit-sys/public_symbol_export.h" #include "version.h" #pragma GCC visibility push(default) +struct libgit_config_set { +struct config_set cs; +}; + +struct libgit_config_set *libgit_configset_alloc (void ) +{ +struct libgit_config_set *cs = +xmalloc (sizeof (struct libgit_config_set )); +git_configset_init (&cs->cs); +return cs; +} + +void libgit_configset_free (struct libgit_config_set *cs) +{ +git_configset_clear (&cs->cs); +free (cs); +} + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename) +{ +return git_configset_add_file (&cs->cs, filename); +} + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key, +int *dest) +{ +return git_configset_get_int (&cs->cs, key, dest); +} + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key, +char **dest) +{ +return git_configset_get_string (&cs->cs, key, dest); +} +const char *libgit_user_agent (void ) {return git_user_agent ();
contrib/libgit-sys/public_symbol_export.h +10 -0
@@ -1,6 +1,16 @@#ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +struct libgit_config_set *libgit_configset_alloc (void ); + +void libgit_configset_free (struct libgit_config_set *cs); + +int libgit_configset_add_file (struct libgit_config_set *cs,const char *filename); + +int libgit_configset_get_int (struct libgit_config_set *cs,const char *key,int *dest); + +int libgit_configset_get_string (struct libgit_config_set *cs,const char *key,char **dest); +const char *libgit_user_agent (void );const char *libgit_user_agent_sanitized (void );
contrib/libgit-sys/src/lib.rs +30 -1
@@ -1,15 +1,44 @@#[cfg(has_std__ffi__c_char)] -use std::ffi::c_char; +use std::ffi::{c_char, c_int};#[cfg(not(has_std__ffi__c_char))] #[allow(non_camel_case_types)] pub type c_char =i8 ; +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int =i32 ; +extern crate libz_sys; +#[allow(non_camel_case_types)] +#[repr( C )] +pub struct libgit_config_set { + _data: [u8 ;0 ], + _marker: core::marker::PhantomData <(*mut u8 , core::marker::PhantomPinned )>, +} +extern "C" {pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ; + +pub fn libgit_configset_alloc () -> *mut libgit_config_set ; +pub fn libgit_configset_free (cs: *mut libgit_config_set ); + +pub fn libgit_configset_add_file (cs: *mut libgit_config_set , filename: *const c_char ) ->c_int ; + +pub fn libgit_configset_get_int ( + cs: *mut libgit_config_set , + key: *const c_char , + int: *mut c_int , + ) ->c_int ; + +pub fn libgit_configset_get_string ( + cs: *mut libgit_config_set , + key: *const c_char , + dest: *mut *mut c_char , + ) ->c_int ; + }#[cfg(test)]
Signature · 1 line
2.48.1.362.g079036d154-goog
PATCH v9 4/4 libgit: add higher-level libgit crate
In reply to Josh SteadmonFrom: Calvin Wan <[email protected]>
The C functions exported by libgit-sys do not provide an idiomatic Rust interface. To make it easier to use these functions via Rust, add a higher-level "libgit" crate, that wraps the lower-level configset API with an interface that is more Rust-y.
This combination of $X and $X-sys crates is a common pattern for FFI in Rust, as documented in "The Cargo Book" [1].
[1] https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
--- .gitignore | 1 + Makefile | 12 ++-- contrib/libgit-rs/Cargo.lock | 77 +++++++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 +++++ contrib/libgit-rs/README.md | 13 ++++ contrib/libgit-rs/build.rs | 4 ++ contrib/libgit-rs/src/config.rs | 106 +++++++++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/src/lib.rs | 4 ++ t/Makefile | 9 ++- 13 files changed, 242 insertions(+), 8 deletions(-) create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644 contrib/libgit-rs/Cargo.toml create mode 100644 contrib/libgit-rs/README.md create mode 100644 contrib/libgit-rs/build.rs create mode 100644 contrib/libgit-rs/src/config.rs create mode 100644 contrib/libgit-rs/src/lib.rs create mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3
.gitignore +1 -0
@@ -250,4 +250,5 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-rs/target /contrib/libgit-sys/target
Makefile +6 -6
@@ -417,7 +417,7 @@ include shared.mak # programs in oss-fuzz/. # # Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and -# test the Rust crate in contrib/libgit-sys. +# test the Rust crates in contrib/libgit-sys and contrib/libgit-rs. # # === Optional library: libintl === #
@@ -3741,7 +3741,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/libgit-sys/target + $(RM) -r contrib/libgit-sys/target contrib/libgit-rs/target $(RM) contrib/libgit-sys/partial_symbol_export.o $(RM) contrib/libgit-sys/hidden_symbol_export.o $(RM) contrib/libgit-sys/libgitpub.a
@@ -3907,14 +3907,14 @@ build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests -.PHONY: libgit-sys -libgit-sys: +.PHONY: libgit-sys libgit-rs +libgit-sys libgit-rs: $(QUIET)(\ - cd contrib/libgit-sys && \ + cd contrib/$@ && \ cargo build \ ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys +all:: libgit-sys libgit-rs endif LIBGIT_PUB_OBJS =
contrib/libgit-rs/Cargo.lock new file +77 -0
77 lines not on this page · raw message
contrib/libgit-rs/Cargo.toml new file +17 -0
@@ -0,0 +1,17 @@ +[package] +name = "libgit" +version = "0.1.0" +edition = "2021" +build = "build.rs" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/[email protected]/ + + +[lib] +path = "src/lib.rs" + +[dependencies] +libgit-sys = { version = "0.1.0", path = "../libgit-sys" } + +[build-dependencies] +autocfg = "1.4.0"
contrib/libgit-rs/README.md new file +13 -0
@@ -0,0 +1,13 @@ +# libgit-rs + +Proof-of-concept Git bindings for Rust. + +```toml +[dependencies] +libgit = "0.1.0" +``` + +## Rust version requirements + +libgit-rs should support Rust versions at least as old as the version included +in Debian stable (currently 1.63).
contrib/libgit-rs/build.rs new file +4 -0
@@ -0,0 +1,4 @@ +pub fn main () { +let ac = autocfg::new (); + ac.emit_has_path ("std::ffi::c_char" ); +}
contrib/libgit-rs/src/config.rs new file +106 -0
106 lines not on this page · raw message
contrib/libgit-rs/src/lib.rs new file +1 -0
@@ -0,0 +1 @@ +pub mod config;
contrib/libgit-rs/testdata/config1 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 1
contrib/libgit-rs/testdata/config2 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventTarget = 1
contrib/libgit-rs/testdata/config3 new file +2 -0
@@ -0,0 +1,2 @@ +[trace2] + eventNesting = 3
contrib/libgit-sys/src/lib.rs +4 -0
@@ -1,3 +1,5 @@ +use std::ffi::c_void; +#[cfg(has_std__ffi__c_char)] use std::ffi::{c_char, c_int};
@@ -19,6 +21,8 @@ pub struct libgit_config_set { }extern "C" { +pub fn free (ptr: *mut c_void ); +pub fn libgit_user_agent () -> *const c_char ;pub fn libgit_user_agent_sanitized () -> *const c_char ;
t/Makefile +7 -2
@@ -178,12 +178,17 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) -.PHONY: libgit-sys-test +.PHONY: libgit-sys-test libgit-rs-test libgit-sys-test: $(QUIET)(\ cd ../contrib/libgit-sys && \ cargo test \ ) +libgit-rs-test: + $(QUIET)(\ + cd ../contrib/libgit-rs && \ + cargo test \ + ) ifdef INCLUDE_LIBGIT_RS -all:: libgit-sys-test +all:: libgit-sys-test libgit-rs-test endif
Signature · 1 line
2.48.1.362.g079036d154-goog
Re: [PATCH v9 0/4] Introduce libgit-rs, a Rust wrapper around libgit.a
In reply to Josh SteadmonHi Josh
The range-diff looks good. It's really nice to see this being added to git.
Best Wishes
Phillip
Quoted 209 lines · Josh Steadmon
This series provides two small Rust wrapper libraries around parts of
Git: "libgit-sys", which exposes a few functions from libgit.a, and "libgit", which provides a more Rust-friendly interface to some of those functions. In addition to included unit tests, at $DAYJOB we have tested building JJ[1] with our library and used it to replace some of the libgit2-rs uses.[1] https://github.com/jj-vcs/jj
There is known NEEDSWORK, but I feel that they can be addressed in follow-up changes, rather than in this series. If you feel otherwise, please let me know:
* Investigate alternative methods of managing symbol visibility & renaming.
* Figure out symbol versioning
Changes in V9:
* Properly initializeMakefilevarLIBGIT_PUB_OBJS.* Pass the correct pointer to free in
libgit_configset_free().Changes in V8:
* Define a privatelibgit_config_setstruct to avoid excessive casting inpublic_symbol_export.c.* Style fixes: merge some
Makefilerules, limit rule line length by defining intermediate variables, add initial empty comment line, add linebreaks in function definitions.Changes in V7:
* Moved the ConfigSet implementation in libgit-rs to aconfigmodule.* Added doc comments for ConfigSet and its methods.
* Fix meson builds by adding new object files to
libgit_sources* Moved
INCLUDE_LIBGIT_RSMakefilechanges earlier in the series, so that we can make it optional to compile some of the libgitpub sources. Squashed V6 patch 5/5 into this series' patch 4/4.* Don't publicly export FFI types in libgit-rs.
* Removed extraneous
-rargument to $(RM) in the clean rules.* Added TODO reminder in Cargo.toml about removing Cargo.lock once we hit a certain minimum supported Rust version.
* Style cleanup in
public_symbol_export.cChanges in V6:
* Rebased onto current master, since V5 was several months old.* Move libgit-sys out of libgit-rs; while this sort of nesting is common in Rust crates with standalone repositories, it doesn't make as much sense when they're contained in the larger Git project's repo.
* Standardize the naming of some of the
Makefiletargets to always include a dash in the "-rs" or "-sys" suffixes.* Clean up READMEs and crate descriptions in preparation for uploading to crates.io.
Changes in V5:
* When building withINCLUDE_LIBGIT_RSdefined, add "-fvisibility=hidden" to CFLAGS. This allows us to manage symbol visibility in libgitpub.a without causingmake allto rebuild from scratch due to changing CFLAGS.* Avoid using
c_intin the higher-level Rust API.* Remove libgitpub.a and intermediate files with
make clean.Changes in V4:
* Drop V3 patch #3, which added wrappers around repository initialization and config access. These are not well-libified, and they are not necessary for JJ's proof-of-concept use case, so let's avoid exporting them for now.* Set a minimum supported Rust version of 1.63. Autodetect whether our Rust version has
c_intandc_chartypes; if not, define them ourselves.* When building libgitpub.a via
build.rs, set DEVELOPER=1 to catch additional errors at build time.* In
build.rs, use themake_cmdcrate to portable select the correct invocation of GNU Make.* Follow naming standards for
_alloc()and_free()functions.* Use String instead of CString in higher-level API.
* Move
libgit_configset_alloc()andlibgit_configset_free()out of upstream Git, to the libgitpub shim library.* In libgitpub, initialize
libgit_config_setstructs in the_alloc()function rather than with a separate_init()function.* Remove unnecessary comments in libgit-sys showing where the wrapped functions were originally defined.
* Fix clippy lint: don't reborrow configfile path references.
* Various typo fixes and
cargo fmtfixes.Changes in V3:
* Renamed cgit-rs to libgit-rs and cgit-sys to libgit-sys*
Makefilecleanup, particularly adding config.mak options that developers can set to run Rust builds and tests by default (Patch 6)* Provide testdata configs for unit tests
* ConfigSet API now uses &Path instead of &str -- more ergonomic for Rust users to pass in and errors out if the path string isn't UTF-8
* Fixed unresolved dependency on libz in Cargo.toml
Calvin Wan (1):
libgit: add higher-level libgit crateJosh Steadmon (3):
common-main: split init and exit code into new files
libgit-sys: introduce Rust wrapper for libgit.a
libgit-sys: also export someconfig_setfunctions.gitignore | 2 + Makefile | 50 ++++++++++ common-exit.c | 26 ++++++ common-init.c | 63 +++++++++++++ common-init.h | 6 ++ common-main.c | 83 +---------------- contrib/libgit-rs/Cargo.lock | 77 ++++++++++++++++ contrib/libgit-rs/Cargo.toml | 17 ++++ contrib/libgit-rs/README.md | 13 +++ contrib/libgit-rs/build.rs | 4 + contrib/libgit-rs/src/config.rs | 106 ++++++++++++++++++++++ contrib/libgit-rs/src/lib.rs | 1 + contrib/libgit-rs/testdata/config1 | 2 + contrib/libgit-rs/testdata/config2 | 2 + contrib/libgit-rs/testdata/config3 | 2 + contrib/libgit-sys/Cargo.lock | 69 ++++++++++++++ contrib/libgit-sys/Cargo.toml | 19 ++++ contrib/libgit-sys/README.md | 4 + contrib/libgit-sys/build.rs | 35 +++++++ contrib/libgit-sys/public_symbol_export.c | 59 ++++++++++++ contrib/libgit-sys/public_symbol_export.h | 18 ++++ contrib/libgit-sys/src/lib.rs | 79 ++++++++++++++++ meson.build | 2 + t/Makefile | 15 +++ 24 files changed, 673 insertions(+), 81 deletions(-)create mode 100644
common-exit.c
create mode 100644common-init.c
create mode 100644common-init.h
create mode 100644 contrib/libgit-rs/Cargo.lock create mode 100644contrib/libgit-rs/Cargo.tomlcreate mode 100644contrib/libgit-rs/README.mdcreate mode 100644contrib/libgit-rs/build.rscreate mode 100644contrib/libgit-rs/src/config.rscreate mode 100644contrib/libgit-rs/src/lib.rscreate mode 100644 contrib/libgit-rs/testdata/config1 create mode 100644 contrib/libgit-rs/testdata/config2 create mode 100644 contrib/libgit-rs/testdata/config3 create mode 100644 contrib/libgit-sys/Cargo.lock create mode 100644contrib/libgit-sys/Cargo.tomlcreate mode 100644contrib/libgit-sys/README.mdcreate mode 100644contrib/libgit-sys/build.rscreate mode 100644contrib/libgit-sys/public_symbol_export.ccreate mode 100644contrib/libgit-sys/public_symbol_export.hcreate mode 100644contrib/libgit-sys/src/lib.rsRange-diff against v8:
1: cd0cb9aa04 = 1: cd0cb9aa04 common-main: split init and exit code into new files 2: 3588a3c3fc ! 2: 8793ff64a7 libgit-sys: introduce Rust wrapper for libgit.a @@ Makefile: $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GIT +all:: libgit-sys +endif + -+LIBGIT_PUB_OBJS = contrib/libgit-sys/public_symbol_export.o ++LIBGIT_PUB_OBJS = ++LIBGIT_PUB_OBJS += contrib/libgit-sys/public_symbol_export.o +LIBGIT_PUB_OBJS += libgit.a +LIBGIT_PUB_OBJS += reftable/libreftable.a +LIBGIT_PUB_OBJS += xdiff/lib.a 3: f4452fffe6 ! 3: ab32bd1d07 libgit-sys: also export some config_set functions @@ contrib/libgit-sys/public_symbol_export.c +void libgit_configset_free(struct libgit_config_set *cs) +{ + git_configset_clear(&cs->cs); -+ free(&cs->cs); ++ free(cs); +} + +int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename)4:
ada9fc0a13! 4:1bf8c5392clibgit: add higher-level libgit crate
@@Makefile: build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
+all:: libgit-sys libgit-rs
endif-
LIBGIT_PUB_OBJS=contrib/libgit-sys/public_symbol_export.o
+LIBGIT_PUB_OBJS=## contrib/libgit-rs/Cargo.lock (new) ##
@@base-commit:
757161efcca150a9a96b312d9e780a071e601a03
Re: [PATCH v9 0/4] Introduce libgit-rs, a Rust wrapper around libgit.a
Quoted 7 lines · [email protected] writes:
Hi Josh
The range-diff looks good. It's really nice to see this being added to git.
Best Wishes
Phillip
Thanks. Let's plan to mark the topic for 'next' unless there are other comments.