serpent-os / libgit2-d

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

libgit2-d

@safe D bindings for libgit2.

Maintainers' notes

This is an incomplete binding, meaning we polish it as we use it. Right now, you may use the binding directly if you're fine with writing non-safe functions or breaking dip1000. Note that the functions themselves are marked as @safe; it's just that some function parameters are simply un-obtainable in an @safe context (e.g. cannot take address of local variable or a pointer to a pointer). By polishing, we modify the function signatures and add attributes according to the rules outlined in the Making It Ergonomic section so that they can be used smoothly in Safe-D.

Generating Bindings

This shouldn't be required. When updating the bindings to new versions, consult Updating Bindings section. If you really need to generate the bindings, build the libgit2 subproject using CMake, install it to a local directory, use clang (NOT gcc!) to preprocess the header file git2.h to git2.i, and lastly run dstep on it.

cmake -DBUILD_TESTS=OFF -B build -S .
make -C build
DESTDIR="$PWD/install" make -C build install
clang -E -I$PWD/install/usr/local/include $PWD/install/usr/local/include/git2.h -o ../../source/git2/git2.i
dstep ../../source/git2/git2.i -o ../../source/git2/bindings.d

Updating Bindings

Thankfully the maintainers of libgit2 have been doing a tremendous job of keeping their changelog detailed. In addition, libgit2 rarely makes huge changes in its public API. Therefore, once we have the initial generated bindings, we can simply update the bindings by hand according to either the changelog or the diffs between tags generated by GitHub.

When hand-authoring these new functions/structs, you may consult the existing generated bindings as a reference.

If the new API is a completely new header file, you can use dstep to process that single header file (without preprocessing) after performing the build and install steps specified in the Generating Bindings section.

Currently, there's a Perl script that performs the "safeification" of the bindings according to the rules below.

Making It Ergonomic

  1. At the very least, all pointer parameters should have the scope attribute except for const(char)*-type parameters, where we're expected to pass a string using someString.toStringz(). If you're only adding a scope attribute, you may just edit it in the bindings.d file.
  2. If a parameter is passed to be assigned (e.g. git_clone, git_remote_lookup), use the scope out attribute instead. You can usually infer this through the API documentation or the paramter (e.g. an out**). If you're only replacing a pointer-to-pointer with a scope out pointer parameter, you may just edit it in the bindings.d file.
  3. All pointer parameters should be replaced with scope ref as much as possible. This primarily applies to structs that have a declared body (such as all structs with the form git_x_options). If you're only replacing a pointer with scope ref, you may just edit it in the bindings.d file. However, note for exceptions as outlined in the rule below.
    • The git_x_options structs are particularly forgiving in that there are two identical functions for initializing them (git_x_init_options and git_x_options_init). In this case, we choose to exempt the git_x_init_options functions from rule (3) and only apply rule (3) on the git_x_options_init functions).
  4. Some structs, particularly structs who do not have a declared body and are assigned through a pointer-to-pointer or a ref to a pointer (such as git_repository and git_remote), cannot be passed as ref since they must be declared as a pointer. In these cases, ignore rule (3) and follow rule (1).
  5. Anything with ref/out disallows passing lvalues to it, therefore rule (3) will break any function that intends you to pass null to indicate an optional parameter. When this happens, copy the edited function into the extra.d file and follow rule (1) for that parameter. For the edited function in the extra.d file, you may add a =null default value to that parameter if desired. For reference, search for the definition of the two git_clone functions.

On the ABI level, the signature of the functions are not changed. This is only for the purpose of satisfying the compiler and adhereing to Safe-D. (If you're wondering why we can't use the in attribute, this is because with --preview=in, in is not allowed in extern(C) functions)

About

License:Other


Languages

Language:D 96.3%Language:Perl 2.3%Language:Meson 1.1%Language:Shell 0.3%