aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/CodingGuidelines
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/CodingGuidelines')
-rw-r--r--Documentation/CodingGuidelines98
1 files changed, 94 insertions, 4 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 1d92b2da03..3263245b03 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -185,8 +185,8 @@ For shell scripts specifically (not exhaustive):
- Even though "local" is not part of POSIX, we make heavy use of it
in our test suite. We do not use it in scripted Porcelains, and
- hopefully nobody starts using "local" before they are reimplemented
- in C ;-)
+ hopefully nobody starts using "local" before all shells that matter
+ support it (notably, ksh from AT&T Research does not support it yet).
- Some versions of shell do not understand "export variable=value",
so we write "variable=value" and then "export variable" on two
@@ -204,6 +204,33 @@ For shell scripts specifically (not exhaustive):
local variable="$value"
local variable="$(command args)"
+ - The common construct
+
+ VAR=VAL command args
+
+ to temporarily set and export environment variable VAR only while
+ "command args" is running is handy, but this triggers an
+ unspecified behaviour according to POSIX when used for a command
+ that is not an external command (like shell functions). Indeed,
+ dash 0.5.10.2-6 on Ubuntu 20.04, /bin/sh on FreeBSD 13, and AT&T
+ ksh all make a temporary assignment without exporting the variable,
+ in such a case. As it does not work portably across shells, do not
+ use this syntax for shell functions. A common workaround is to do
+ an explicit export in a subshell, like so:
+
+ (incorrect)
+ VAR=VAL func args
+
+ (correct)
+ (
+ VAR=VAL &&
+ export VAR &&
+ func args
+ )
+
+ but be careful that the effect "func" makes to the variables in the
+ current shell will be lost across the subshell boundary.
+
- Use octal escape sequences (e.g. "\302\242"), not hexadecimal (e.g.
"\xc2\xa2") in printf format strings, since hexadecimal escape
sequences are not portable.
@@ -214,6 +241,16 @@ For C programs:
- We use tabs to indent, and interpret tabs as taking up to
8 spaces.
+ - Nested C preprocessor directives are indented after the hash by one
+ space per nesting level.
+
+ #if FOO
+ # include <foo.h>
+ # if BAR
+ # include <bar.h>
+ # endif
+ #endif
+
- We try to keep to at most 80 characters per line.
- As a Git developer we assume you have a reasonably modern compiler
@@ -221,6 +258,14 @@ For C programs:
ensure your patch is clear of all compiler warnings we care about,
by e.g. "echo DEVELOPER=1 >>config.mak".
+ - When using DEVELOPER=1 mode, you may see warnings from the compiler
+ like "error: unused parameter 'foo' [-Werror=unused-parameter]",
+ which indicates that a function ignores its argument. If the unused
+ parameter can't be removed (e.g., because the function is used as a
+ callback and has to match a certain interface), you can annotate
+ the individual parameters with the UNUSED (or MAYBE_UNUSED)
+ keyword, like "int foo UNUSED".
+
- We try to support a wide range of C compilers to compile Git with,
including old ones. As of Git v2.35.0 Git requires C99 (we check
"__STDC_VERSION__"). You should not use features from a newer C
@@ -234,7 +279,7 @@ For C programs:
. since around 2007 with 2b6854c863a, we have been using
initializer elements which are not computable at load time. E.g.:
- const char *args[] = {"constant", variable, NULL};
+ const char *args[] = { "constant", variable, NULL };
. since early 2012 with e1327023ea, we have been using an enum
definition whose last element is followed by a comma. This, like
@@ -266,7 +311,9 @@ For C programs:
v12.01, 2022-03-28).
- Variables have to be declared at the beginning of the block, before
- the first statement (i.e. -Wdeclaration-after-statement).
+ the first statement (i.e. -Wdeclaration-after-statement). It is
+ encouraged to have a blank line between the end of the declarations
+ and the first statement in the block.
- NULL pointers shall be written as NULL, not as 0.
@@ -286,6 +333,13 @@ For C programs:
while( condition )
func (bar+1);
+ - A binary operator (other than ",") and ternary conditional "?:"
+ have a space on each side of the operator to separate it from its
+ operands. E.g. "A + 1", not "A+1".
+
+ - A unary operator (other than "." and "->") have no space between it
+ and its operand. E.g. "(char *)ptr", not "(char *) ptr".
+
- Do not explicitly compare an integral value with constant 0 or '\0',
or a pointer value with constant NULL. For instance, to validate that
counted array <ptr, cnt> is initialized but has no elements, write:
@@ -531,6 +585,42 @@ For C programs:
use your own debugger and arguments. Example: `GIT_DEBUGGER="ddd --gdb"
./bin-wrappers/git log` (See `wrap-for-bin.sh`.)
+ - The primary data structure that a subsystem 'S' deals with is called
+ `struct S`. Functions that operate on `struct S` are named
+ `S_<verb>()` and should generally receive a pointer to `struct S` as
+ first parameter. E.g.
+
+ struct strbuf;
+
+ void strbuf_add(struct strbuf *buf, ...);
+
+ void strbuf_reset(struct strbuf *buf);
+
+ is preferred over:
+
+ struct strbuf;
+
+ void add_string(struct strbuf *buf, ...);
+
+ void reset_strbuf(struct strbuf *buf);
+
+ - There are several common idiomatic names for functions performing
+ specific tasks on a structure `S`:
+
+ - `S_init()` initializes a structure without allocating the
+ structure itself.
+
+ - `S_release()` releases a structure's contents without freeing the
+ structure.
+
+ - `S_clear()` is equivalent to `S_release()` followed by `S_init()`
+ such that the structure is directly usable after clearing it. When
+ `S_clear()` is provided, `S_init()` shall not allocate resources
+ that need to be released again.
+
+ - `S_free()` releases a structure's contents and frees the
+ structure.
+
For Perl programs:
- Most of the C guidelines above apply.