CONVENTIONS.md 7.25 KB
Newer Older
1
# Libgit2 Conventions
2

3 4
We like to keep the source consistent and readable.  Herein are some
guidelines that should help with that.
5

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
## Compatibility

`libgit2` runs on many different platforms with many different compilers.
It is written in [ANSI C](http://en.wikipedia.org/wiki/ANSI_C) (a.k.a. C89)
with some specific standards for function and type naming, code formatting,
and testing.

We try to avoid more recent extensions to maximize portability.  We also, to
the greatest extent possible, try to avoid lots of `#ifdef`s inside the core
code base.  This is somewhat unavoidable, but since it can really hamper
maintainability, we keep it to a minimum.

## Match Surrounding Code

If there is one rule to take away from this document, it is *new code should
match the surrounding code in a way that makes it impossible to distinguish
the new from the old.* Consistency is more important to us than anyone's
personal opinion about where braces should be placed or spaces vs. tabs.

If a section of code is being completely rewritten, it is okay to bring it
in line with the standards that are laid out here, but we will not accept
submissions that contain a large number of changes that are merely
reformatting.
29

30
## Naming Things
31

32 33 34 35 36
All external types and functions start with `git_` and all `#define` macros
start with `GIT_`.  The `libgit2` API is mostly broken into related
functional modules each with a corresponding header.  All functions in a
module should be named like `git_modulename_functioname()`
(e.g. `git_repository_open()`).
37

38 39
Functions with a single output parameter should name that parameter `out`.
Multiple outputs should be named `foo_out`, `bar_out`, etc.
40

41 42
Parameters of type `git_oid` should be named `id`, or `foo_id`.  Calls that
return an OID should be named `git_foo_id`.
43

44 45 46
Where a callback function is used, the function should also include a
user-supplied extra input that is a `void *` named "payload" that will be
passed through to the callback at each invocation.
47

48
## Typedefs
49

50 51 52
Wherever possible, use `typedef`.  In some cases, if a structure is just a
collection of function pointers, the pointer types don't need to be
separately typedef'd, but loose function pointer types should be.
53

54
## Exports
55 56 57

All exported functions must be declared as:

58
```c
59
GIT_EXTERN(result_type) git_modulename_functionname(arg_list);
Ben Straub committed
60
```
61

62
## Internals
63

64
Functions whose *modulename* is followed by two underscores,
65
for example `git_odb__read_packed`, are semi-private functions.
66 67 68
They are primarily intended for use within the library itself,
and may disappear or change their signature in a future release.

69 70 71 72 73
## Parameters

Out parameters come first.

Whenever possible, pass argument pointers as `const`.  Some structures (such
74 75
as `git_repository` and `git_index`) have mutable internal structure that
prevents this.
76 77

Callbacks should always take a `void *` payload as their last parameter.
78 79
Callback pointers are grouped with their payloads, and typically come last
when passed as arguments:
80

81 82
```c
int git_foo(git_repository *repo, git_foo_cb callback, void *payload);
83 84 85 86 87 88 89 90 91 92
```

## Memory Ownership

Some APIs allocate memory which the caller is responsible for freeing; others
return a pointer into a buffer that's owned by some other object.  Make this
explicit in the documentation.

## Return codes

93 94 95 96 97 98 99 100
Most public APIs should return an `int` error code.  As is typical with most
C library functions, a zero value indicates success and a negative value
indicates failure.

Some bindings will transform these returned error codes into exception
types, so returning a semantically appropriate error code is important.
Check
[`include/git2/errors.h`](https://github.com/libgit2/libgit2/blob/development/include/git2/errors.h)
101 102
for the return codes already defined.

103 104
In your implementation, use `giterr_set()` to provide extended error
information to callers.
105

106 107 108
If a `libgit2` function internally invokes another function that reports an
error, but the error is not propagated up, use `giterr_clear()` to prevent
callers from getting the wrong error message later on.
109 110


111
## Structs
112

113
Most public types should be opaque, e.g.:
114

Ben Straub committed
115
```C
116
typedef struct git_odb git_odb;
Ben Straub committed
117
```
118

119 120 121 122 123 124 125 126
...with allocation functions returning an "instance" created within
the library, and not within the application.  This allows the type
to grow (or shrink) in size without rebuilding client code.

To preserve ABI compatibility, include an `int version` field in all opaque
structures, and initialize to the latest version in the construction call.
Increment the "latest" version whenever the structure changes, and try to only
append to the end of the structure.
127

128
## Option Structures
129

130 131 132 133
If a function's parameter count is too high, it may be desirable to package
up the options in a structure.  Make them transparent, include a version
field, and provide an initializer constant or constructor.  Using these
structures should be this easy:
134

135 136 137 138 139
```C
git_foo_options opts = GIT_FOO_OPTIONS_INIT;
opts.baz = BAZ_OPTION_ONE;
git_foo(&opts);
```
140

141
## Enumerations
142

143 144 145
Typedef all enumerated types.  If each option stands alone, use the enum
type for passing them as parameters; if they are flags to be OR'ed together,
pass them as `unsigned int` or `uint32_t` or some appropriate type.
146

147
## Code Layout
148

149 150
Try to keep lines less than 80 characters long.  This is a loose
requirement, but going significantly over 80 columns is not nice.
151

152 153 154 155 156 157 158 159
Use common sense to wrap most code lines; public function declarations
can use a couple of different styles:

```c
/** All on one line is okay if it fits */
GIT_EXTERN(int) git_foo_simple(git_oid *id);

/** Otherwise one argument per line is a good next step */
160
GIT_EXTERN(int) git_foo_id(
161 162 163
	git_oid **out,
	int a,
	int b);
164 165
```

166
Indent with tabs; set your editor's tab width to 4 for best effect.
167

168 169 170
Avoid trailing whitespace and only commit Unix-style newlines (i.e. no CRLF
in the repository - just set `core.autocrlf` to true if you are writing code
on a Windows machine).
171

172
## Documentation
173

174
All comments should conform to Doxygen "javadoc" style conventions for
175 176
formatting the public API documentation.  Try to document every parameter,
and keep the comments up to date if you change the parameter list.
177

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
## Public Header Template

Use this template when creating a new public header.

```C
#ifndef INCLUDE_git_${filename}_h__
#define INCLUDE_git_${filename}_h__

#include "git/common.h"

/**
 * @file git/${filename}.h
 * @brief Git some description
 * @defgroup git_${filename} some description routines
 * @ingroup Git
 * @{
 */
GIT_BEGIN_DECL

/* ... definitions ... */

/** @} */
GIT_END_DECL
#endif
Ben Straub committed
202
```
203

204 205 206 207 208 209 210 211
## Inlined functions

All inlined functions must be declared as:

```C
GIT_INLINE(result_type) git_modulename_functionname(arg_list);
```

212 213
## Tests

Russell Belfer committed
214
`libgit2` uses the [clar](https://github.com/vmg/clar) testing framework.
215 216 217 218 219 220 221 222 223 224 225 226 227

All PRs should have corresponding tests.

* If the PR fixes an existing issue, the test should fail prior to applying
  the PR and succeed after applying it.
* If the PR is for new functionality, then the tests should exercise that
  new functionality to a certain extent.  We don't require 100% coverage
  right now (although we are getting stricter over time).

When adding new tests, we prefer if you attempt to reuse existing test data
(in `tests-clar/resources/`) if possible.  If you are going to add new test
repositories, please try to strip them of unnecessary files (e.g. sample
hooks, etc).