mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 21:08:56 +00:00
Merge pull request #1386 from arrbee/update-docs
Update contributing and conventions
This commit is contained in:
commit
bb19532c5f
@ -7,41 +7,93 @@ your help.
|
|||||||
|
|
||||||
We hang out in the #libgit2 channel on irc.freenode.net.
|
We hang out in the #libgit2 channel on irc.freenode.net.
|
||||||
|
|
||||||
|
Also, feel free to open an
|
||||||
|
[Issue](https://github.com/libgit2/libgit2/issues/new) to start a discussion
|
||||||
|
about any concerns you have. We like to use Issues for that so there is an
|
||||||
|
easily accessible permanent record of the conversation.
|
||||||
|
|
||||||
## Reporting Bugs
|
## Reporting Bugs
|
||||||
|
|
||||||
First, know which version of libgit2 your problem is in. Compile and test
|
First, know which version of libgit2 your problem is in and include it in
|
||||||
against the `development` branch to avoid re-reporting an issue that's already
|
your bug report. This can either be a tag (e.g.
|
||||||
been fixed.
|
[v0.17.0](https://github.com/libgit2/libgit2/tree/v0.17.0) ) or a commit
|
||||||
|
SHA (e.g.
|
||||||
|
[01be7863](https://github.com/libgit2/libgit2/commit/01be786319238fd6507a08316d1c265c1a89407f)
|
||||||
|
). Using [`git describe`](http://git-scm.com/docs/git-describe) is a great
|
||||||
|
way to tell us what version you're working with.
|
||||||
|
|
||||||
It's *incredibly* helpful to be able to reproduce the problem. Please include
|
If you're not running against the latest `development` branch version,
|
||||||
a bit of code and/or a zipped repository (if possible). Note that some of the
|
please compile and test against that to avoid re-reporting an issue that's
|
||||||
developers are employees of GitHub, so if your repository is private, find us
|
already been fixed.
|
||||||
on IRC and we'll figure out a way to help you.
|
|
||||||
|
It's *incredibly* helpful to be able to reproduce the problem. Please
|
||||||
|
include a list of steps, a bit of code, and/or a zipped repository (if
|
||||||
|
possible). Note that some of the libgit2 developers are employees of
|
||||||
|
GitHub, so if your repository is private, find us on IRC and we'll figure
|
||||||
|
out a way to help you.
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
|
|
||||||
Life will be a lot easier for you if you create a named branch for your
|
Our work flow is a typical GitHub flow, where contributors fork the
|
||||||
contribution, rather than just using your fork's `development`.
|
[libgit2 repository](https://github.com/libgit2/libgit2), make their changes
|
||||||
|
on branch, and submit a
|
||||||
|
[Pull Request](https://help.github.com/articles/using-pull-requests)
|
||||||
|
(a.k.a. "PR").
|
||||||
|
|
||||||
It's helpful if you include a nice description of your change with your PR; if
|
Life will be a lot easier for you (and us) if you follow this pattern
|
||||||
someone has to read the whole diff to figure out why you're contributing in the
|
(i.e. fork, named branch, submit PR). If you use your fork's `development`
|
||||||
first place, you're less likely to get feedback and have your change merged in.
|
branch, things can get messy.
|
||||||
|
|
||||||
|
Please include a nice description of your changes with your PR; if we have
|
||||||
|
to read the whole diff to figure out why you're contributing in the first
|
||||||
|
place, you're less likely to get feedback and have your change merged in.
|
||||||
|
|
||||||
## Porting Code From Other Open-Source Projects
|
## Porting Code From Other Open-Source Projects
|
||||||
|
|
||||||
The most common case here is porting code from core Git. Git is a GPL project,
|
`libgit2` is licensed under the terms of the GPL v2 with a linking
|
||||||
which means that in order to port code to this project, we need the explicit
|
exception. Any code brought in must be compatible with those terms.
|
||||||
permission of the author. Check the
|
|
||||||
|
The most common case is porting code from core Git. Git is a pure GPL
|
||||||
|
project, which means that in order to port code to this project, we need the
|
||||||
|
explicit permission of the author. Check the
|
||||||
[`git.git-authors`](https://github.com/libgit2/libgit2/blob/development/git.git-authors)
|
[`git.git-authors`](https://github.com/libgit2/libgit2/blob/development/git.git-authors)
|
||||||
file for authors who have already consented; feel free to add someone if you've
|
file for authors who have already consented; feel free to add someone if
|
||||||
obtained their consent.
|
you've obtained their consent.
|
||||||
|
|
||||||
Other licenses have other requirements; check the license of the library you're
|
Other licenses have other requirements; check the license of the library
|
||||||
porting code *from* to see what you need to do.
|
you're porting code *from* to see what you need to do. As a general rule,
|
||||||
|
MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0
|
||||||
|
license typically doesn't work due to GPL incompatibility.
|
||||||
|
|
||||||
## Styleguide
|
## Style Guide
|
||||||
|
|
||||||
We like to keep the source code consistent and easy to read. Maintaining this
|
`libgit2` is written in [ANSI C](http://en.wikipedia.org/wiki/ANSI_C)
|
||||||
takes some discipline, but it's been more than worth it. Take a look at the
|
(a.k.a. C89) with some specific conventions for function and type naming,
|
||||||
|
code formatting, and testing.
|
||||||
|
|
||||||
|
We like to keep the source code consistent and easy to read. Maintaining
|
||||||
|
this takes some discipline, but it's been more than worth it. Take a look
|
||||||
|
at the
|
||||||
[conventions file](https://github.com/libgit2/libgit2/blob/development/CONVENTIONS.md).
|
[conventions file](https://github.com/libgit2/libgit2/blob/development/CONVENTIONS.md).
|
||||||
|
|
||||||
|
## Starter Projects
|
||||||
|
|
||||||
|
So, you want to start helping out with `libgit2`? That's fantastic? We
|
||||||
|
welcome contributions and we promise we'll try to be nice.
|
||||||
|
|
||||||
|
If you want to jump in, you can look at our issues list to see if there
|
||||||
|
are any unresolved issues to jump in on. Also, here is a list of some
|
||||||
|
smaller project ideas that could help you become familiar with the code
|
||||||
|
base and make a nice first step:
|
||||||
|
|
||||||
|
* Convert a `git_*modulename*_foreach()` callback-based iteration API
|
||||||
|
into a `git_*modulename*_iterator` object with a create/advance style
|
||||||
|
of API. This helps folks writing language bindings and usually isn't
|
||||||
|
too complicated.
|
||||||
|
* Write a new `examples/` program that mirrors a particular core git
|
||||||
|
command. (See `examples/diff.c` for example.) This lets you (and us)
|
||||||
|
easily exercise a particular facet of the API and measure compatability
|
||||||
|
and feature parity with core git.
|
||||||
|
* Submit a PR to clarify documentation! While we do try to document all of
|
||||||
|
the APIs, your fresh eyes on the documentation will find areas that are
|
||||||
|
confusing much more easily.
|
||||||
|
146
CONVENTIONS.md
146
CONVENTIONS.md
@ -1,12 +1,39 @@
|
|||||||
# Libgit2 Conventions
|
# Libgit2 Conventions
|
||||||
|
|
||||||
We like to keep the source consistent and readable. Herein are some guidelines
|
We like to keep the source consistent and readable. Herein are some
|
||||||
that should help with that.
|
guidelines that should help with that.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
## Naming Things
|
## Naming Things
|
||||||
|
|
||||||
All types and functions start with `git_`, and all #define macros start with `GIT_`.
|
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()`).
|
||||||
|
|
||||||
Functions with a single output parameter should name that parameter `out`.
|
Functions with a single output parameter should name that parameter `out`.
|
||||||
Multiple outputs should be named `foo_out`, `bar_out`, etc.
|
Multiple outputs should be named `foo_out`, `bar_out`, etc.
|
||||||
@ -14,26 +41,27 @@ Multiple outputs should be named `foo_out`, `bar_out`, etc.
|
|||||||
Parameters of type `git_oid` should be named `id`, or `foo_id`. Calls that
|
Parameters of type `git_oid` should be named `id`, or `foo_id`. Calls that
|
||||||
return an OID should be named `git_foo_id`.
|
return an OID should be named `git_foo_id`.
|
||||||
|
|
||||||
Where there is a callback passed in, the `void *` that is passed into it should
|
Where a callback function is used, the function should also include a
|
||||||
be named "payload".
|
user-supplied extra input that is a `void *` named "payload" that will be
|
||||||
|
passed through to the callback at each invocation.
|
||||||
|
|
||||||
## Typedef
|
## Typedefs
|
||||||
|
|
||||||
Wherever possible, use `typedef`. If a structure is just a collection of
|
Wherever possible, use `typedef`. In some cases, if a structure is just a
|
||||||
function pointers, the pointer types don't need to be separately typedef'd, but
|
collection of function pointers, the pointer types don't need to be
|
||||||
loose function pointer types should be.
|
separately typedef'd, but loose function pointer types should be.
|
||||||
|
|
||||||
## Exports
|
## Exports
|
||||||
|
|
||||||
All exported functions must be declared as:
|
All exported functions must be declared as:
|
||||||
|
|
||||||
```C
|
```c
|
||||||
GIT_EXTERN(result_type) git_modulename_functionname(arg_list);
|
GIT_EXTERN(result_type) git_modulename_functionname(arg_list);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Internals
|
## Internals
|
||||||
|
|
||||||
Functions whose modulename is followed by two underscores,
|
Functions whose *modulename* is followed by two underscores,
|
||||||
for example `git_odb__read_packed`, are semi-private functions.
|
for example `git_odb__read_packed`, are semi-private functions.
|
||||||
They are primarily intended for use within the library itself,
|
They are primarily intended for use within the library itself,
|
||||||
and may disappear or change their signature in a future release.
|
and may disappear or change their signature in a future release.
|
||||||
@ -43,42 +71,46 @@ and may disappear or change their signature in a future release.
|
|||||||
Out parameters come first.
|
Out parameters come first.
|
||||||
|
|
||||||
Whenever possible, pass argument pointers as `const`. Some structures (such
|
Whenever possible, pass argument pointers as `const`. Some structures (such
|
||||||
as `git_repository` and `git_index`) have internal structure that prevents
|
as `git_repository` and `git_index`) have mutable internal structure that
|
||||||
this.
|
prevents this.
|
||||||
|
|
||||||
Callbacks should always take a `void *` payload as their last parameter.
|
Callbacks should always take a `void *` payload as their last parameter.
|
||||||
Callback pointers are grouped with their payloads, and come last when passed as
|
Callback pointers are grouped with their payloads, and typically come last
|
||||||
arguments:
|
when passed as arguments:
|
||||||
|
|
||||||
```C
|
```c
|
||||||
int foo(git_repository *repo, git_foo_cb callback, void *payload);
|
int git_foo(git_repository *repo, git_foo_cb callback, void *payload);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Memory Ownership
|
## Memory Ownership
|
||||||
|
|
||||||
Some APIs allocate memory which the caller is responsible for freeing; others
|
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
|
return a pointer into a buffer that's owned by some other object. Make this
|
||||||
explicit in the documentation.
|
explicit in the documentation.
|
||||||
|
|
||||||
|
|
||||||
## Return codes
|
## Return codes
|
||||||
|
|
||||||
Return an `int` when a public API can fail in multiple ways. These may be
|
Most public APIs should return an `int` error code. As is typical with most
|
||||||
transformed into exception types in some bindings, so returning a semantically
|
C library functions, a zero value indicates success and a negative value
|
||||||
appropriate error code is important. Check
|
indicates failure.
|
||||||
[`errors.h`](https://github.com/libgit2/libgit2/blob/development/include/git2/errors.h)
|
|
||||||
|
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)
|
||||||
for the return codes already defined.
|
for the return codes already defined.
|
||||||
|
|
||||||
Use `giterr_set` to provide extended error information to callers.
|
In your implementation, use `giterr_set()` to provide extended error
|
||||||
|
information to callers.
|
||||||
|
|
||||||
If an error is not to be propagated, use `giterr_clear` to prevent callers from
|
If a `libgit2` function internally invokes another function that reports an
|
||||||
getting the wrong error message later on.
|
error, but the error is not propagated up, use `giterr_clear()` to prevent
|
||||||
|
callers from getting the wrong error message later on.
|
||||||
|
|
||||||
|
|
||||||
## Opaque Structs
|
## Structs
|
||||||
|
|
||||||
Most types should be opaque, e.g.:
|
Most public types should be opaque, e.g.:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
typedef struct git_odb git_odb;
|
typedef struct git_odb git_odb;
|
||||||
@ -95,10 +127,10 @@ append to the end of the structure.
|
|||||||
|
|
||||||
## Option Structures
|
## Option Structures
|
||||||
|
|
||||||
If a function's parameter count is too high, it may be desirable to package up
|
If a function's parameter count is too high, it may be desirable to package
|
||||||
the options in a structure. Make them transparent, include a version field,
|
up the options in a structure. Make them transparent, include a version
|
||||||
and provide an initializer constant or constructor. Using these structures
|
field, and provide an initializer constant or constructor. Using these
|
||||||
should be this easy:
|
structures should be this easy:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
git_foo_options opts = GIT_FOO_OPTIONS_INIT;
|
git_foo_options opts = GIT_FOO_OPTIONS_INIT;
|
||||||
@ -108,30 +140,40 @@ git_foo(&opts);
|
|||||||
|
|
||||||
## Enumerations
|
## Enumerations
|
||||||
|
|
||||||
Typedef all enumerated types. If each option stands alone, use the enum type
|
Typedef all enumerated types. If each option stands alone, use the enum
|
||||||
for passing them as parameters; if they are flags, pass them as `unsigned int`.
|
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.
|
||||||
|
|
||||||
## Code Layout
|
## Code Layout
|
||||||
|
|
||||||
Try to keep lines less than 80 characters long. Use common sense to wrap most
|
Try to keep lines less than 80 characters long. This is a loose
|
||||||
code lines; public function declarations should use this convention:
|
requirement, but going significantly over 80 columns is not nice.
|
||||||
|
|
||||||
```C
|
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 */
|
||||||
GIT_EXTERN(int) git_foo_id(
|
GIT_EXTERN(int) git_foo_id(
|
||||||
git_oid **out,
|
git_oid **out,
|
||||||
int a,
|
int a,
|
||||||
int b);
|
int b);
|
||||||
```
|
```
|
||||||
|
|
||||||
Indentation is done with tabs; set your editor's tab width to 3 for best effect.
|
Indent with tabs; set your editor's tab width to 4 for best effect.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
All comments should conform to Doxygen "javadoc" style conventions for
|
All comments should conform to Doxygen "javadoc" style conventions for
|
||||||
formatting the public API documentation. Try to document every parameter, and
|
formatting the public API documentation. Try to document every parameter,
|
||||||
keep the comments up to date if you change the parameter list.
|
and keep the comments up to date if you change the parameter list.
|
||||||
|
|
||||||
|
|
||||||
## Public Header Template
|
## Public Header Template
|
||||||
|
|
||||||
@ -167,3 +209,19 @@ All inlined functions must be declared as:
|
|||||||
GIT_INLINE(result_type) git_modulename_functionname(arg_list);
|
GIT_INLINE(result_type) git_modulename_functionname(arg_list);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
`libgit2` uses the [clar](https://github.com/vmg/clar) testing framework.
|
||||||
|
|
||||||
|
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).
|
||||||
|
@ -15,28 +15,9 @@ static int resolve_to_tree(
|
|||||||
git_repository *repo, const char *identifier, git_tree **tree)
|
git_repository *repo, const char *identifier, git_tree **tree)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
size_t len = strlen(identifier);
|
|
||||||
git_oid oid;
|
|
||||||
git_object *obj = NULL;
|
git_object *obj = NULL;
|
||||||
|
|
||||||
/* try to resolve as OID */
|
if (git_revparse_single(&obj, repo, identifier) < 0)
|
||||||
if (git_oid_fromstrn(&oid, identifier, len) == 0)
|
|
||||||
git_object_lookup_prefix(&obj, repo, &oid, len, GIT_OBJ_ANY);
|
|
||||||
|
|
||||||
/* try to resolve as reference */
|
|
||||||
if (obj == NULL) {
|
|
||||||
git_reference *ref, *resolved;
|
|
||||||
if (git_reference_lookup(&ref, repo, identifier) == 0) {
|
|
||||||
git_reference_resolve(&resolved, ref);
|
|
||||||
git_reference_free(ref);
|
|
||||||
if (resolved) {
|
|
||||||
git_object_lookup(&obj, repo, git_reference_target(resolved), GIT_OBJ_ANY);
|
|
||||||
git_reference_free(resolved);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj == NULL)
|
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
switch (git_object_type(obj)) {
|
switch (git_object_type(obj)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user