Rewrite conventions to be more complete
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 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 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
diff --git a/CONVENTIONS.md b/CONVENTIONS.md
index 06d3e87..ea5e40e 100644
--- a/CONVENTIONS.md
+++ b/CONVENTIONS.md
@@ -1,107 +1,163 @@
-libgit2 conventions
-===================
+# Libgit2 Conventions
-Namespace Prefixes
-------------------
+We like to keep the source consistent and readable. Herein are some guidelines
+that should help with that.
-All types and functions start with 'git_'.
-All #define macros start with 'GIT_'.
+## Naming Things
+All types and functions start with `git_`, and all #define macros start with `GIT_`.
-Type Definitions
-----------------
+Functions with a single output parameter should name that parameter `out`.
+Multiple outputs should be named `foo_out`, `bar_out`, etc.
-Most types should be opaque, e.g.:
+Parameters of type `git_oid` should be named `id`, or `foo_id`. Calls that
+return an OID should be named `git_foo_id`.
-```C
- typedef struct git_odb git_odb;
-```
+Where there is a callback passed in, the `void *` that is passed into it should
+be named "payload".
-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.
+## Typedef
+Wherever possible, use `typedef`. 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.
-Public Exported Function Definitions
-------------------------------------
+## Exports
All exported functions must be declared as:
```C
- GIT_EXTERN(result_type) git_modulename_functionname(arg_list);
+GIT_EXTERN(result_type) git_modulename_functionname(arg_list);
```
-
-Semi-Private Exported Functions
--------------------------------
+## Internals
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,
and may disappear or change their signature in a future release.
+## Parameters
+
+Out parameters come first.
+
+Whenever possible, pass argument pointers as `const`. Some structures (such
+as `git_repository` and `git_index`) have internal structure that prevents
+this.
+
+Callbacks should always take a `void *` payload as their last parameter.
+Callback pointers are grouped with their payloads, and come last when passed as
+arguments:
+
+```C
+int foo(git_repository *repo, git_foo_cb callback, void *payload);
+```
+
+
+## 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
+
+Return an `int` when a public API can fail in multiple ways. These may be
+transformed into exception types in some bindings, so returning a semantically
+appropriate error code is important. Check
+[`errors.h`](https://github.com/libgit2/libgit2/blob/development/include/git2/errors.h)
+for the return codes already defined.
+
+Use `giterr_set` to provide extended error information to callers.
-Calling Conventions
--------------------
+If an error is not to be propagated, use `giterr_clear` to prevent callers from
+getting the wrong error message later on.
-Functions should prefer to return a 'int' to indicate success or
-failure and supply any output through the first argument (or first
-few arguments if multiple outputs are supplied).
-int status codes are 0 for GIT_OK and < 0 for an error.
-This permits common POSIX result testing:
+## Opaque Structs
+
+Most types should be opaque, e.g.:
```C
- if (git_odb_open(&odb, path))
- abort("odb open failed");
+typedef struct git_odb git_odb;
```
-Functions returning a pointer may return NULL instead of an int
-if there is only one type of failure (GIT_ENOMEM).
+...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.
-Functions returning a pointer may also return NULL if the common
-case needed by the application is strictly success/failure and a
-(possibly slower) function exists that the caller can use to get
-more detailed information. Parsing common data structures from
-on-disk formats is a good example of this pattern; in general a
-"corrupt" entity can be treated as though it does not exist but
-a more sophisticated "fsck" support function can report how the
-entity is malformed.
+## Option Structures
+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:
-Documentation Fomatting
------------------------
+```C
+git_foo_options opts = GIT_FOO_OPTIONS_INIT;
+opts.baz = BAZ_OPTION_ONE;
+git_foo(&opts);
+```
-All comments should conform to Doxygen "javadoc" style conventions
-for formatting the public API documentation.
+## Enumerations
+Typedef all enumerated types. If each option stands alone, use the enum type
+for passing them as parameters; if they are flags, pass them as `unsigned int`.
-Public Header Format
---------------------
+## Code Layout
-All public headers defining types, functions or macros must use
-the following form, where ${filename} is the name of the file,
-after replacing non-identifier characters with '_'.
+Try to keep lines less than 80 characters long. Use common sense to wrap most
+code lines; public function declarations should use this convention:
```C
- #ifndef INCLUDE_git_${filename}_h__
- #define INCLUDE_git_${filename}_h__
+GIT_EXTERN(int) git_foo_id(
+ git_oid **out,
+ int a,
+ int b);
+```
+
+Public headers are indented with spaces, three to a tab. Internal code is
+indented with tabs; set your editor's tab width to 3 for best effect.
+
- #include "git/common.h"
+## Documentation
- /**
- * @file git/${filename}.h
- * @brief Git some description
- * @defgroup git_${filename} some description routines
- * @ingroup Git
- * @{
- */
- GIT_BEGIN_DECL
+All comments should conform to Doxygen "javadoc" style conventions for
+formatting the public API documentation. Try to document every parameter, and
+keep the comments up to date if you change the parameter list.
- ... definitions ...
- /** @} */
- GIT_END_DECL
- #endif
+## 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
```
+
+