Blame CONVENTIONS.md

Packit Service 20376f
# Libgit2 Conventions
Packit Service 20376f
Packit Service 20376f
We like to keep the source consistent and readable.  Herein are some
Packit Service 20376f
guidelines that should help with that.
Packit Service 20376f
Packit Service 20376f
## External API
Packit Service 20376f
Packit Service 20376f
We have a few rules to avoid surprising ways of calling functions and
Packit Service 20376f
some rules for consumers of the library to avoid stepping on each
Packit Service 20376f
other's toes.
Packit Service 20376f
Packit Service 20376f
 - Property accessors return the value directly (e.g. an `int` or
Packit Service 20376f
   `const char *`) but if a function can fail, we return a `int` value
Packit Service 20376f
   and the output parameters go first in the parameter list, followed
Packit Service 20376f
   by the object that a function is operating on, and then any other
Packit Service 20376f
   arguments the function may need.
Packit Service 20376f
Packit Service 20376f
 - If a function returns an object as a return value, that function is
Packit Service 20376f
   a getter and the object's lifetime is tied to the parent
Packit Service 20376f
   object. Objects which are returned as the first argument as a
Packit Service 20376f
   pointer-to-pointer are owned by the caller and it is responsible
Packit Service 20376f
   for freeing it. Strings are returned via `git_buf` in order to
Packit Service 20376f
   allow for re-use and safe freeing.
Packit Service 20376f
Packit Service 20376f
 - Most of what libgit2 does relates to I/O so as a general rule
Packit Service 20376f
   you should assume that any function can fail due to errors as even
Packit Service 20376f
   getting data from the filesystem can result in all sorts of errors
Packit Service 20376f
   and complex failure cases.
Packit Service 20376f
Packit Service 20376f
 - Paths inside the Git system are separated by a slash (0x2F). If a
Packit Service 20376f
   function accepts a path on disk, then backslashes (0x5C) are also
Packit Service 20376f
   accepted on Windows.
Packit Service 20376f
Packit Service 20376f
 - Do not mix allocators. If something has been allocated by libgit2,
Packit Service 20376f
   you do not know which is the right free function in the general
Packit Service 20376f
   case. Use the free functions provided for each object type.
Packit Service 20376f
Packit Service 20376f
## Compatibility
Packit Service 20376f
Packit Service 20376f
`libgit2` runs on many different platforms with many different compilers.
Packit Service 20376f
Packit Service 20376f
The public API of `libgit2` is [ANSI C](http://en.wikipedia.org/wiki/ANSI_C)
Packit Service 20376f
(a.k.a. C89) compatible.
Packit Service 20376f
Packit Service 20376f
Internally, `libgit2` is written using a portable subset of C99 - in order
Packit Service 20376f
to maximize compatibility (e.g. with MSVC) we avoid certain C99
Packit Service 20376f
extensions.  Specifically, we keep local variable declarations at the tops
Packit Service 20376f
of blocks only and we avoid `//` style comments.
Packit Service 20376f
Packit Service 20376f
Also, to the greatest extent possible, we try to avoid lots of `#ifdef`s
Packit Service 20376f
inside the core code base.  This is somewhat unavoidable, but since it can
Packit Service 20376f
really hamper maintainability, we keep it to a minimum.
Packit Service 20376f
Packit Service 20376f
## Match Surrounding Code
Packit Service 20376f
Packit Service 20376f
If there is one rule to take away from this document, it is *new code should
Packit Service 20376f
match the surrounding code in a way that makes it impossible to distinguish
Packit Service 20376f
the new from the old.* Consistency is more important to us than anyone's
Packit Service 20376f
personal opinion about where braces should be placed or spaces vs. tabs.
Packit Service 20376f
Packit Service 20376f
If a section of code is being completely rewritten, it is okay to bring it
Packit Service 20376f
in line with the standards that are laid out here, but we will not accept
Packit Service 20376f
submissions that contain a large number of changes that are merely
Packit Service 20376f
reformatting.
Packit Service 20376f
Packit Service 20376f
## Naming Things
Packit Service 20376f
Packit Service 20376f
All external types and functions start with `git_` and all `#define` macros
Packit Service 20376f
start with `GIT_`.  The `libgit2` API is mostly broken into related
Packit Service 20376f
functional modules each with a corresponding header.  All functions in a
Packit Service 20376f
module should be named like `git_modulename_functioname()`
Packit Service 20376f
(e.g. `git_repository_open()`).
Packit Service 20376f
Packit Service 20376f
Functions with a single output parameter should name that parameter `out`.
Packit Service 20376f
Multiple outputs should be named `foo_out`, `bar_out`, etc.
Packit Service 20376f
Packit Service 20376f
Parameters of type `git_oid` should be named `id`, or `foo_id`.  Calls that
Packit Service 20376f
return an OID should be named `git_foo_id`.
Packit Service 20376f
Packit Service 20376f
Where a callback function is used, the function should also include a
Packit Service 20376f
user-supplied extra input that is a `void *` named "payload" that will be
Packit Service 20376f
passed through to the callback at each invocation.
Packit Service 20376f
Packit Service 20376f
## Typedefs
Packit Service 20376f
Packit Service 20376f
Wherever possible, use `typedef`.  In some cases, if a structure is just a
Packit Service 20376f
collection of function pointers, the pointer types don't need to be
Packit Service 20376f
separately typedef'd, but loose function pointer types should be.
Packit Service 20376f
Packit Service 20376f
## Exports
Packit Service 20376f
Packit Service 20376f
All exported functions must be declared as:
Packit Service 20376f
Packit Service 20376f
```c
Packit Service 20376f
GIT_EXTERN(result_type) git_modulename_functionname(arg_list);
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
## Internals
Packit Service 20376f
Packit Service 20376f
Functions whose *modulename* is followed by two underscores,
Packit Service 20376f
for example `git_odb__read_packed`, are semi-private functions.
Packit Service 20376f
They are primarily intended for use within the library itself,
Packit Service 20376f
and may disappear or change their signature in a future release.
Packit Service 20376f
Packit Service 20376f
## Parameters
Packit Service 20376f
Packit Service 20376f
Out parameters come first.
Packit Service 20376f
Packit Service 20376f
Whenever possible, pass argument pointers as `const`.  Some structures (such
Packit Service 20376f
as `git_repository` and `git_index`) have mutable internal structure that
Packit Service 20376f
prevents this.
Packit Service 20376f
Packit Service 20376f
Callbacks should always take a `void *` payload as their last parameter.
Packit Service 20376f
Callback pointers are grouped with their payloads, and typically come last
Packit Service 20376f
when passed as arguments:
Packit Service 20376f
Packit Service 20376f
```c
Packit Service 20376f
int git_foo(git_repository *repo, git_foo_cb callback, void *payload);
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
## Memory Ownership
Packit Service 20376f
Packit Service 20376f
Some APIs allocate memory which the caller is responsible for freeing; others
Packit Service 20376f
return a pointer into a buffer that's owned by some other object.  Make this
Packit Service 20376f
explicit in the documentation.
Packit Service 20376f
Packit Service 20376f
## Return codes
Packit Service 20376f
Packit Service 20376f
Most public APIs should return an `int` error code.  As is typical with most
Packit Service 20376f
C library functions, a zero value indicates success and a negative value
Packit Service 20376f
indicates failure.
Packit Service 20376f
Packit Service 20376f
Some bindings will transform these returned error codes into exception
Packit Service 20376f
types, so returning a semantically appropriate error code is important.
Packit Service 20376f
Check
Packit Service 20376f
[`include/git2/errors.h`](https://github.com/libgit2/libgit2/blob/development/include/git2/errors.h)
Packit Service 20376f
for the return codes already defined.
Packit Service 20376f
Packit Service 20376f
In your implementation, use `giterr_set()` to provide extended error
Packit Service 20376f
information to callers.
Packit Service 20376f
Packit Service 20376f
If a `libgit2` function internally invokes another function that reports an
Packit Service 20376f
error, but the error is not propagated up, use `giterr_clear()` to prevent
Packit Service 20376f
callers from getting the wrong error message later on.
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
## Structs
Packit Service 20376f
Packit Service 20376f
Most public types should be opaque, e.g.:
Packit Service 20376f
Packit Service 20376f
```C
Packit Service 20376f
typedef struct git_odb git_odb;
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
...with allocation functions returning an "instance" created within
Packit Service 20376f
the library, and not within the application.  This allows the type
Packit Service 20376f
to grow (or shrink) in size without rebuilding client code.
Packit Service 20376f
Packit Service 20376f
To preserve ABI compatibility, include an `int version` field in all opaque
Packit Service 20376f
structures, and initialize to the latest version in the construction call.
Packit Service 20376f
Increment the "latest" version whenever the structure changes, and try to only
Packit Service 20376f
append to the end of the structure.
Packit Service 20376f
Packit Service 20376f
## Option Structures
Packit Service 20376f
Packit Service 20376f
If a function's parameter count is too high, it may be desirable to package
Packit Service 20376f
up the options in a structure.  Make them transparent, include a version
Packit Service 20376f
field, and provide an initializer constant or constructor.  Using these
Packit Service 20376f
structures should be this easy:
Packit Service 20376f
Packit Service 20376f
```C
Packit Service 20376f
git_foo_options opts = GIT_FOO_OPTIONS_INIT;
Packit Service 20376f
opts.baz = BAZ_OPTION_ONE;
Packit Service 20376f
git_foo(&opts);
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
## Enumerations
Packit Service 20376f
Packit Service 20376f
Typedef all enumerated types.  If each option stands alone, use the enum
Packit Service 20376f
type for passing them as parameters; if they are flags to be OR'ed together,
Packit Service 20376f
pass them as `unsigned int` or `uint32_t` or some appropriate type.
Packit Service 20376f
Packit Service 20376f
## Code Layout
Packit Service 20376f
Packit Service 20376f
Try to keep lines less than 80 characters long.  This is a loose
Packit Service 20376f
requirement, but going significantly over 80 columns is not nice.
Packit Service 20376f
Packit Service 20376f
Use common sense to wrap most code lines; public function declarations
Packit Service 20376f
can use a couple of different styles:
Packit Service 20376f
Packit Service 20376f
```c
Packit Service 20376f
/** All on one line is okay if it fits */
Packit Service 20376f
GIT_EXTERN(int) git_foo_simple(git_oid *id);
Packit Service 20376f
Packit Service 20376f
/** Otherwise one argument per line is a good next step */
Packit Service 20376f
GIT_EXTERN(int) git_foo_id(
Packit Service 20376f
	git_oid **out,
Packit Service 20376f
	int a,
Packit Service 20376f
	int b);
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
Indent with tabs; set your editor's tab width to 4 for best effect.
Packit Service 20376f
Packit Service 20376f
Avoid trailing whitespace and only commit Unix-style newlines (i.e. no CRLF
Packit Service 20376f
in the repository - just set `core.autocrlf` to true if you are writing code
Packit Service 20376f
on a Windows machine).
Packit Service 20376f
Packit Service 20376f
## Documentation
Packit Service 20376f
Packit Service 20376f
All comments should conform to Doxygen "javadoc" style conventions for
Packit Service 20376f
formatting the public API documentation.  Try to document every parameter,
Packit Service 20376f
and keep the comments up to date if you change the parameter list.
Packit Service 20376f
Packit Service 20376f
## Public Header Template
Packit Service 20376f
Packit Service 20376f
Use this template when creating a new public header.
Packit Service 20376f
Packit Service 20376f
```C
Packit Service 20376f
#ifndef INCLUDE_git_${filename}_h__
Packit Service 20376f
#define INCLUDE_git_${filename}_h__
Packit Service 20376f
Packit Service 20376f
#include "git/common.h"
Packit Service 20376f
Packit Service 20376f
/**
Packit Service 20376f
 * @file git/${filename}.h
Packit Service 20376f
 * @brief Git some description
Packit Service 20376f
 * @defgroup git_${filename} some description routines
Packit Service 20376f
 * @ingroup Git
Packit Service 20376f
 * @{
Packit Service 20376f
 */
Packit Service 20376f
GIT_BEGIN_DECL
Packit Service 20376f
Packit Service 20376f
/* ... definitions ... */
Packit Service 20376f
Packit Service 20376f
/** @} */
Packit Service 20376f
GIT_END_DECL
Packit Service 20376f
#endif
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
## Inlined functions
Packit Service 20376f
Packit Service 20376f
All inlined functions must be declared as:
Packit Service 20376f
Packit Service 20376f
```C
Packit Service 20376f
GIT_INLINE(result_type) git_modulename_functionname(arg_list);
Packit Service 20376f
```
Packit Service 20376f
Packit Service 20376f
`GIT_INLINE` (or `inline`) should not be used in public headers in order
Packit Service 20376f
to preserve ANSI C compatibility.
Packit Service 20376f
Packit Service 20376f
## Tests
Packit Service 20376f
Packit Service 20376f
`libgit2` uses the [clar](https://github.com/vmg/clar) testing framework.
Packit Service 20376f
Packit Service 20376f
All PRs should have corresponding tests.
Packit Service 20376f
Packit Service 20376f
* If the PR fixes an existing issue, the test should fail prior to applying
Packit Service 20376f
  the PR and succeed after applying it.
Packit Service 20376f
* If the PR is for new functionality, then the tests should exercise that
Packit Service 20376f
  new functionality to a certain extent.  We don't require 100% coverage
Packit Service 20376f
  right now (although we are getting stricter over time).
Packit Service 20376f
Packit Service 20376f
When adding new tests, we prefer if you attempt to reuse existing test data
Packit Service 20376f
(in `tests-clar/resources/`) if possible.  If you are going to add new test
Packit Service 20376f
repositories, please try to strip them of unnecessary files (e.g. sample
Packit Service 20376f
hooks, etc).