1# Contributing to librdkafka
2
3(This document is based on [curl's CONTRIBUTE.md](https://github.com/curl/curl/blob/master/docs/CONTRIBUTE.md) - thank you!)
4
5This document is intended to offer guidelines on how to best contribute to the
6librdkafka project. This concerns new features as well as bug fixes and
7general improvements.
8
9### License and copyright
10
11When contributing with code, you agree to put your changes and new code under
12the same license librdkafka is already using unless stated and agreed
13otherwise.
14
15When changing existing source code, you do not alter the copyright of the
16original file(s). The copyright will still be owned by the original creator(s)
17or those who have been assigned copyright by the original author(s).
18
19By submitting a patch to the librdkafka, you are assumed to have the right
20to the code and to be allowed by your employer or whatever to hand over that
21patch/code to us. We will credit you for your changes as far as possible, to
22give credit but also to keep a trace back to who made what changes. Please
23always provide us with your full real name when contributing!
24
25Official librdkafka project maintainer(s) assume ownership of all accepted
26submissions.
27
28## Write a good patch
29
30### Follow code style
31
32When writing C code, follow the code style already established in
33the project. Consistent style makes code easier to read and mistakes less
34likely to happen.
35
36See the end of this document for the C style guide to use in librdkafka.
37
38
39### Write Separate Changes
40
41It is annoying when you get a huge patch from someone that is said to fix 511
42odd problems, but discussions and opinions don't agree with 510 of them - or
43509 of them were already fixed in a different way. Then the person merging
44this change needs to extract the single interesting patch from somewhere
45within the huge pile of source, and that gives a lot of extra work.
46
47Preferably, each fix that correct a problem should be in its own patch/commit
48with its own description/commit message stating exactly what they correct so
49that all changes can be selectively applied by the maintainer or other
50interested parties.
51
52Also, separate changes enable bisecting much better when we track problems
53and regression in the future.
54
55### Patch Against Recent Sources
56
57Please try to make your patches against latest master branch.
58
59### Test Cases
60
61Bugfixes should also include a new test case in the regression test suite
62that verifies the bug is fixed.
63Create a new tests/00<freenumber>-<short_bug_description>.c file and
64try to reproduce the issue in its most simple form.
65Verify that the test case fails for earlier versions and passes with your
66bugfix in-place.
67
68New features and APIs should also result in an added test case.
69
70Submitted patches must pass all existing tests.
71For more information on the test suite see [tests/README.md]
72
73
74
75## How to get your changes into the main sources
76
77File a [pull request on github](https://github.com/edenhill/librdkafka/pulls)
78
79Your change will be reviewed and discussed there and you will be
80expected to correct flaws pointed out and update accordingly, or the change
81risk stalling and eventually just get deleted without action. As a submitter
82of a change, you are the owner of that change until it has been merged.
83
84Make sure to monitor your PR on github and answer questions and/or
85fix nits/flaws. This is very important. We will take lack of replies as a
86sign that you're not very anxious to get your patch accepted and we tend to
87simply drop such changes.
88
89When you adjust your pull requests after review, please squash the
90commits so that we can review the full updated version more easily
91and keep history cleaner.
92
93For example:
94
95    # Interactive rebase to let you squash/fixup commits
96    $ git rebase -i master
97
98    # Mark fixes-on-fixes commits as 'fixup' (or just 'f') in the
99    # first column. These will be silently integrated into the
100    # previous commit, so make sure to move the fixup-commit to
101    # the line beneath the parent commit.
102
103    # Since this probably rewrote the history of previously pushed
104    # commits you will need to make a force push, which is usually
105    # a bad idea but works good for pull requests.
106    $ git push --force origin your_feature_branch
107
108
109### Write good commit messages
110
111A short guide to how to write good commit messages.
112
113    ---- start ----
114    [area]: [short line describing the main effect] [(#issuenumber)]
115           -- empty line --
116    [full description, no wider than 72 columns that describe as much as
117    possible as to why this change is made, and possibly what things
118    it fixes and everything else that is related]
119    ---- stop ----
120
121Example:
122
123    cgrp: Restart query timer on all heartbeat failures (#10023)
124
125    If unhandled errors were received in HeartbeatResponse
126    the cgrp could get stuck in a state where it would not
127    refresh its coordinator.
128
129
130**Important**: Rebase your PR branch on top of master (`git rebase -i master`)
131               and squash interim commits (to make a clean and readable git history)
132               before pushing. Use force push to keep your history clean even after
133               the initial PR push.
134
135**Note**: Good PRs with bad commit messages or messy commit history
136          such as "fixed review comment", will be squashed up in
137          to a single commit with a proper commit message.
138
139
140### Add changelog
141
142If the changes in the PR affects the end user in any way, such as for a user
143visible bug fix, new feature, API or doc change, etc, a release changelog item
144needs to be added to [CHANGELOG.md](CHANGELOG.md) for the next release.
145
146Add a single line to the appropriate section (Enhancements, Fixes, ..)
147outlining the change, an issue number (if any), and your name or GitHub
148user id for attribution.
149
150E.g.:
151```
152## Enhancements
153 * Improve commit() async parameter documentation (Paul Nit, #123)
154```
155
156
157
158# librdkafka C style guide
159
160## Function and globals naming
161
162Use self-explanatory hierarchical snake-case naming.
163Pretty much all symbols should start with `rd_kafka_`, followed by
164their subsystem (e.g., `cgrp`, `broker`, `buf`, etc..), followed by an
165action (e.g, `find`, `get`, `clear`, ..).
166
167
168## Variable naming
169
170For existing types use the type prefix as variable name.
171The type prefix is typically the first part of struct member fields.
172Example:
173
174  * `rd_kafka_broker_t` has field names starting with `rkb_..`, thus broker
175     variable names should be named `rkb`
176
177
178For other types use reasonably concise but descriptive names.
179`i` and `j` are typical int iterators.
180
181## Variable declaration
182
183Variables must be declared at the head of a scope, no in-line variable
184declarations are allowed.
185
186## Indenting
187
188Use 8 spaces indent, same as the Linux kernel.
189In emacs, use `c-set-style "linux`.
190For C++, use Google's C++ style.
191
192## Comments
193
194Use `/* .. */` comments, not `// ..`
195
196For functions, use doxygen syntax, e.g.:
197
198    /**
199     * @brief <short description>
200     * ..
201     * @returns <something..>
202     */
203
204
205Make sure to comment non-obvious code and situations where the full
206context of an operation is not easily graspable.
207
208Also make sure to update existing comments when the code changes.
209
210
211## Line length
212
213Try hard to keep line length below 80 characters, when this is not possible
214exceed it with reason.
215
216
217## Braces
218
219Braces go on the same line as their enveloping statement:
220
221    int some_func (..) {
222      while (1) {
223        if (1) {
224          do something;
225          ..
226        } else {
227          do something else;
228          ..
229        }
230      }
231
232      /* Single line scopes should not have braces */
233      if (1)
234        hi();
235      else if (2)
236        /* Say hello */
237        hello();
238      else
239        bye();
240
241
242## Spaces
243
244All expression parentheses should be prefixed and suffixed with a single space:
245
246    int some_func (int a) {
247
248        if (1)
249          ....;
250
251        for (i = 0 ; i < 19 ; i++) {
252
253
254        }
255    }
256
257
258Use space around operators:
259
260    int a = 2;
261
262    if (b >= 3)
263       c += 2;
264
265Except for these:
266
267    d++;
268    --e;
269
270
271## New block on new line
272
273New blocks should be on a new line:
274
275    if (1)
276      new();
277    else
278      old();
279
280
281## Parentheses
282
283Don't assume the reader knows C operator precedence by heart for complex
284statements, add parentheses to ease readability.
285
286
287## ifdef hell
288
289Avoid ifdef's as much as possible.
290Platform support checking should be performed in configure.librdkafka.
291
292
293
294
295
296# librdkafka C++ style guide
297
298Follow [Google's C++ style guide](https://google.github.io/styleguide/cppguide.html)
299