mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-02 21:34:15 +00:00
365 lines
8.5 KiB
Markdown
365 lines
8.5 KiB
Markdown
# libgit2 Coding Style
|
|
|
|
This documentation describes the preferred coding style for the libgit2 project.
|
|
While not all parts of our code base conform to this coding style, the outlined
|
|
rules are what we aim for.
|
|
|
|
Note that in no case do we accept changes that convert huge parts of the code
|
|
base to use our coding style. Instead, it is encouraged to modernize small parts
|
|
of code you're going to modify anyway for a given change you want to introduce.
|
|
A good rule to follow is the Boy Scout Rule: "Leave the campground cleaner than
|
|
you found it."
|
|
|
|
## C Coding Style
|
|
|
|
The following sections define the coding style for all code files and headers.
|
|
|
|
### Indentation and Alignment
|
|
|
|
Code is indented by tabs, where a tab is 8 spaces. Each opening scope increases
|
|
the indentation level.
|
|
|
|
```c
|
|
int foobar(int void)
|
|
{
|
|
if (condition)
|
|
doit();
|
|
/* Body */
|
|
}
|
|
```
|
|
|
|
Switch statements have their `case`s aligned with the `switch` keyword. Case
|
|
bodies are indented by an additional level. Case bodies should not open their
|
|
own scope to declare variables.
|
|
|
|
```c
|
|
switch (c) {
|
|
case 'a':
|
|
case 'b':
|
|
return 0;
|
|
default:
|
|
return -1;
|
|
}
|
|
```
|
|
|
|
Multi-line conditions should be aligned with the opening brace of the current
|
|
statement:
|
|
|
|
```c
|
|
if (one_very_long_condition(c) &&
|
|
another_very_long_condition(c))
|
|
doit();
|
|
```
|
|
|
|
### Spaces
|
|
|
|
There must be no space between the function and its arguments, arguments must be
|
|
separated by a space:
|
|
|
|
```c
|
|
int doit(int first_arg, int second_arg);
|
|
doit(1, 2);
|
|
```
|
|
|
|
For any binary or ternary operators, the arguments and separator must be
|
|
separated by a space:
|
|
|
|
```c
|
|
1 + 2;
|
|
x ? x : NULL;
|
|
```
|
|
|
|
Unary operators do not have a space between them and the argument they refer to:
|
|
|
|
```c
|
|
*c
|
|
&c
|
|
```
|
|
|
|
The `sizeof` operator always must not have a space and must use braces around
|
|
the type:
|
|
|
|
```
|
|
sizeof(int)
|
|
```
|
|
|
|
There must be a space after the keywords `if`, `switch`, `case`, `do` and
|
|
`while`.
|
|
|
|
### Braces
|
|
|
|
Functions must have their opening brace on the following line:
|
|
|
|
```c
|
|
void foobar(void)
|
|
{
|
|
doit();
|
|
}
|
|
```
|
|
|
|
For conditions, braces should be placed on the same line as the condition:
|
|
|
|
```c
|
|
if (condition(c)) {
|
|
doit();
|
|
dothat();
|
|
}
|
|
|
|
while (true) {
|
|
doit();
|
|
}
|
|
```
|
|
|
|
In case a condition's body has a single line, only, it's allowed to omit braces,
|
|
except if any of its `else if` or `else` branches has more than one line:
|
|
|
|
```c
|
|
if (condition(c))
|
|
doit();
|
|
|
|
if (condition(c))
|
|
doit();
|
|
else if (other_condition(c))
|
|
doit();
|
|
|
|
/* This example must use braces as the `else if` requires them. */
|
|
if (condition(c)) {
|
|
doit();
|
|
} else if (other_condition(c)) {
|
|
doit();
|
|
dothat();
|
|
} else {
|
|
abort();
|
|
}
|
|
```
|
|
|
|
### Comments
|
|
|
|
Comments must use C-style `/* */` comments. C++-style `// `comments are not
|
|
allowed in our codebase. This is a strict requirement as libgit2 tries to be
|
|
compliant with the ISO C90 standard, which only allows C-style comments.
|
|
|
|
Single-line comments may have their opening and closing tag on the same line:
|
|
|
|
```c
|
|
/* This is a short comment. */
|
|
```
|
|
|
|
For multi-line comments, the opening and closing tag should be empty:
|
|
|
|
```c
|
|
/*
|
|
* This is a rather long and potentially really unwiedly but informative
|
|
* multiline comment that helps quite a lot.
|
|
*/
|
|
```
|
|
|
|
Public functions must have documentation that explain their usage, internal
|
|
functions should have a comment. We use Docurium to generate documentation
|
|
derived from these comments, which uses syntax similar to Doxygen. The first
|
|
line should be a short summary of what the function does. More in-depth
|
|
explanation should be separated from that first line by an empty line.
|
|
Parameters and return values should be documented via `@return` and `@param`
|
|
tags:
|
|
|
|
```c
|
|
/*
|
|
* Froznicate the string.
|
|
*
|
|
* Froznicate the string by foobaring its internal structure into a more obvious
|
|
* translation. Note that the returned string is a newly allocated string that
|
|
* shall be `free`d by the caller.
|
|
*
|
|
* @param s String to froznicate
|
|
* @return A newly allocated string or `NULL` in case an error occurred.
|
|
*/
|
|
char *froznicate(const char *s);
|
|
```
|
|
|
|
### Variables
|
|
|
|
Variables must be declared at the beginning of their scope. This is a strict
|
|
requirement as libgit2 tries to be compliant with the ISO C90 standard, which
|
|
forbids mixed declarations and code:
|
|
|
|
```c
|
|
void foobar(void)
|
|
{
|
|
char *c = NULL;
|
|
int a, b;
|
|
|
|
a = 0;
|
|
b = 1;
|
|
|
|
return c;
|
|
}
|
|
```
|
|
|
|
### Naming
|
|
|
|
Variables must have all-lowercase names. In case a variable name has multiple
|
|
words, words should be separated by an underscore `_` character. While
|
|
recommended to use descriptive naming, common variable names like `i` for
|
|
indices are allowed.
|
|
|
|
All public functions must have a `git` prefix as well as a prefix indicating
|
|
their respective subsystem. E.g. a function that opens a repository should be
|
|
called `git_repository_open()`. Functions that are not public but declared in
|
|
an internal header file for use by other subsystems should follow the same
|
|
naming pattern. File-local static functions must not have a `git` prefix, but
|
|
should have a prefix indicating their respective subsystem.
|
|
|
|
All structures declared in the libgit2 project must have a `typedef`, we do not
|
|
use `struct type` variables. Type names follow the same schema as functions.
|
|
|
|
### Error Handling
|
|
|
|
The libgit2 project mostly uses error codes to indicate errors. Error codes are
|
|
always of type `int`, where `0` indicates success and a negative error code
|
|
indicates an error case. In some cases, positive error codes may be used to
|
|
indicate special cases. Returned values that are not an error code should be
|
|
returned via an out parameter. Out parameters must always come first in the list
|
|
of arguments.
|
|
|
|
```c
|
|
int doit(const char **out, int arg)
|
|
{
|
|
if (!arg)
|
|
return -1;
|
|
*out = "Got an argument";
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
To avoid repetitive and fragile error handling in case a function has resources
|
|
that need to be free'd, we use `goto out`s:
|
|
|
|
```c
|
|
int doit(char **out, int arg)
|
|
{
|
|
int error = 0;
|
|
char *c;
|
|
|
|
c = malloc(strlen("Got an argument") + 1);
|
|
if (!c) {
|
|
error = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (!arg) {
|
|
error = -1;
|
|
goto out;
|
|
}
|
|
|
|
strcpy(c, "Got an argument")
|
|
*out = c;
|
|
|
|
out:
|
|
if (error)
|
|
free(c);
|
|
return error;
|
|
}
|
|
```
|
|
|
|
When calling functions that return an error code, you should assign the error
|
|
code to an `error` variable and, in case an error case is indicated and no
|
|
custom error handling is required, return that error code:
|
|
|
|
```c
|
|
int foobar(void)
|
|
{
|
|
int error;
|
|
|
|
if ((error = doit()) < 0)
|
|
return error;
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
When doing multiple function calls where all of the functions return an error
|
|
code, it's common practice to chain these calls together:
|
|
|
|
```c
|
|
int doit(void)
|
|
{
|
|
int error;
|
|
|
|
if ((error = dothis()) < 0 ||
|
|
(error = dothat()) < 0)
|
|
return error;
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
## CMake Coding Style
|
|
|
|
The following section defines the coding style for our CMake build system.
|
|
|
|
### Indentation
|
|
|
|
Code is indented by tabs, where a tab is 8 spaces. Each opening scope increases
|
|
the indentation level.
|
|
|
|
```cmake
|
|
if(CONDITION)
|
|
doit()
|
|
endif()
|
|
```
|
|
|
|
### Spaces
|
|
|
|
There must be no space between keywords and their opening brace. While this is
|
|
the same as in our C codebase for function calls, this also applies to
|
|
conditional keywords. This is done to avoid the awkward-looking `else ()`
|
|
statement.
|
|
|
|
```cmake
|
|
if(CONDITION)
|
|
doit()
|
|
else()
|
|
dothat()
|
|
endif()
|
|
```
|
|
|
|
### Case
|
|
|
|
While CMake is completely case-insensitive when it comes to function calls, we
|
|
want to agree on a common coding style for this. To reduce the danger of
|
|
repetitive strain injuries, all function calls should be lower-case (NB: this is
|
|
not currently the case yet, but introduced as a new coding style by this
|
|
document).
|
|
|
|
Variables are written all-uppercase. In contrast to functions, variables are
|
|
case-sensitive in CMake. As CMake itself uses upper-case variables in all
|
|
places, we should follow suit and do the same.
|
|
|
|
Control flow keywords must be all lowercase. In contrast to that, test keywords
|
|
must be all uppercase:
|
|
|
|
```cmake
|
|
if(NOT CONDITION)
|
|
doit()
|
|
elseif(FOO AND BAR)
|
|
dothat()
|
|
endif()
|
|
```
|
|
|
|
### Targets
|
|
|
|
CMake code should not use functions that modify the global scope but prefer
|
|
their targeted equivalents, instead. E.g. instead of using
|
|
`include_directories()`, you must use `target_include_directories()`. An
|
|
exception to this rule is setting up global compiler flags like warnings or
|
|
flags required to set up the build type.
|
|
|
|
### Dependencies
|
|
|
|
Dependencies should not be discovered or set up in the main "CMakeLists.txt"
|
|
module. Instead, they should either have their own module in our top-level
|
|
"cmake/" directory or have a "CMakeLists.txt" in their respective "deps/"
|
|
directory in case it is a vendored library. All dependencies should expose
|
|
interface library targets that can be linked against with
|
|
`target_link_libraries()`.
|