1# Contributing
2
3Feedback and contributions are very welcome!
4
5Here's help on how to make contributions, divided into the following sections:
6
7The quick-read part:
8* general information,
9* vulnerability reporting,
10* documentation.
11
12The long-read part:
13* code changes,
14* how to check proposed changes before submitting them,
15* reuse of other libraries, frameworks etc.
16
17## General information
18
19For specific proposals, please provide them as
20[pull requests](https://github.com/quotient-im/libQuotient/pulls)
21or
22[issues](https://github.com/quotient-im/libQuotient/issues)
23For general discussion, feel free to use our Matrix room:
24[#quotient:matrix.org](https://matrix.to/#/#quotient:matrix.org).
25
26If you're new to the project (or FLOSS in general),
27[issues tagged as easy](https://github.com/quotient-im/libQuotient/labels/easy)
28are smaller tasks that may typically take 1-3 days.
29You are welcome aboard!
30
31### Pull requests and different branches recommended
32
33Pull requests are preferred, since they are specific.
34See the GitHub Help [articles about pull requests](https://help.github.com/articles/using-pull-requests/)
35to learn how to deal with them.
36
37We recommend creating different branches for different (logical)
38changes, and creating a pull request when you're done into the master branch.
39See the GitHub documentation on
40[creating branches](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/)
41and
42[using pull requests](https://help.github.com/articles/using-pull-requests/).
43
44### How we handle proposals
45
46We use GitHub to track all changes via its
47[issue tracker](https://github.com/quotient-im/libQuotient/issues) and
48[pull requests](https://github.com/quotient-im/libQuotient/pulls).
49Specific changes are proposed using those mechanisms.
50Issues are assigned to an individual who works on it and then marks it complete.
51If there are questions or objections, the conversation area of that
52issue or pull request is used to resolve it.
53
54<!--
55### Developer Certificate of Origin (DCO) - not enforced yet
56
57All contributions (including pull requests) must agree to
58the [Developer Certificate of Origin (DCO) version 1.1](doc/dco.txt).
59This is exactly the same one created and used by the Linux kernel developers
60and posted on <http://developercertificate.org/>.
61This is a developer's certification that he or she has the right to
62submit the patch for inclusion into the project.
63
64Simply submitting a contribution implies this agreement, however,
65please include a "Signed-off-by" tag in every patch
66(this tag is a conventional way to confirm that you agree to the DCO).
67You can do this with <tt>git commit --signoff</tt> (the <tt>-s</tt> flag
68is a synonym for <tt>--signoff</tt>).
69
70Another way to do this is to write the following at the end of the commit
71message, on a line by itself separated by a blank line from the body of
72the commit:
73
74    Signed-off-by: YOUR NAME <YOUR.EMAIL@EXAMPLE.COM>
75
76You can signoff by default in this project by creating a file
77(say "git-template") that contains
78some blank lines and the signed-off-by text above;
79then configure git to use that as a commit template.  For example:
80
81    git config commit.template ~/cii-best-practices-badge/git-template
82
83It's not practical to fix old contributions in git, so if one is forgotten,
84do not try to fix them.  We presume that if someone sometimes used a DCO,
85a commit without a DCO is an accident and the DCO still applies.
86-->
87### License
88
89Unless a contributor explicitly specifies otherwise, we assume contributors
90to agree that all contributed code is released either under *LGPL v2.1 or later*.
91This is more than just [LGPL v2.1 libQuotient now uses](./COPYING)
92because the project plans to switch to LGPL v3 for library code in the near future.
93<!-- The below is invalid yet!
94All new contributed material that is not executable, including all text when not executed, is also released under the
95[Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/) or later.
96-->
97
98Any components proposed for reuse should have a license that permits releasing
99a derivative work under *LGPL v2.1 or later* or LGPL v3. Moreover, the license of
100a proposed component should be approved by OSI, no exceptions.
101
102## Vulnerability reporting (security issues) - see [SECURITY.md](./SECURITY.md)
103
104## Documentation changes
105
106Most of the documentation is in Markdown format. All Markdown files use the .md
107filename extension. Any help on fixing/extending these is more than welcome.
108
109Where reasonable, limit yourself to Markdown that will be accepted by different
110markdown processors (e.g., what is specified by CommonMark or the original
111Markdown). In practice, as long as libQuotient is hosted at GitHub,
112[GFM (GitHub-flavoured Markdown)](https://help.github.com/articles/github-flavored-markdown/)
113is used to show those files in a browser, so it's fine to use its extensions.
114In particular, you can mark code snippets with the programming language used;
115blank lines separate paragraphs, newlines inside a paragraph do *not* force a line break.
116
117Beware - this is *not* the same markdown algorithm used by GitHub when it
118renders issue or pull comments; in those cases
119[newlines in paragraph-like content are considered as real line breaks](https://help.github.com/articles/writing-on-github/);
120unfortunately this other algorithm is *also* called GitHub-flavoured markdown.
121(Yes, it'd be better if there were different names for different things.)
122
123In your markdown, please don't use tab characters and avoid "bare" URLs.
124In a hyperlink, the link text and URL should be on the same line.
125While historically we didn't care about the line length in markdown texts
126(and more often than not put the whole paragraph into one line), this is subject
127to change anytime soon, with 80-character limit _recommendation_
128(which is softer than the limit for C/C++ code) imposed on everything
129_except hyperlinks_ (because wrapping hyperlinks breaks the rendering).
130
131Do not use trailing two spaces for line breaks, since these cannot be seen
132and may be silently removed by some tools. If, for whatever reason, a blank line
133is not an option, use <tt>&lt;br&nbsp;/&gt;</tt> (an HTML break).
134
135## End of TL;DR
136
137If you don't plan/have substantial contributions, you can end reading here. Further sections are for those who's going to actively hack on the library code.
138
139## Code changes
140
141The code should strive to be DRY (don't repeat yourself), clear, and obviously
142correct (i.e. buildable). Some technical debt is inevitable,
143just don't bankrupt us with it. Refactoring is welcome.
144
145### Code style and formatting
146
147As of Quotient 0.6, the C++ standard for newly written code is C++17, with a few
148restrictions, notably:
149* standard library's _deduction guides_ cannot be used to lighten up syntax
150  in template instantiation, i.e. you have to still write
151  `std::array<int, 2> { 1, 2 }` instead of `std::array { 1, 2 }` or use helpers
152  like `std::make_pair` - once we move over to the later Apple toolchain, this
153  will be no more necessary.
154* enumerators and slots cannot have `[[attributes]]` because moc of Qt 5.9
155  chokes on them. This will be lifted when we move on to Qt 5.12 for the oldest
156  supported version.
157* things from `std::filesystem` cannot be used yet until we push the oldest
158  required g++/libc to version 8.
159
160The code style is defined by `.clang-format`, and in general, all C++ files
161should follow it. Files with minor deviations from the defined style are still
162accepted in PRs; however, unless explicitly marked with `// clang-format off`
163and `// clang-format on`, these deviations will be rectified any commit soon
164after.
165
166Additional considerations:
167* 4-space indents, no tabs, no trailing spaces, no last empty lines. If you
168  spot the code abusing these - thank you for fixing it.
169* Prefer keeping lines within 80 characters. Slight overflows are ok only
170  if that helps readability.
171* Please don't make "hypocritical structs" with protected or private members.
172  In general, `struct` is used to denote a plain-old-data structure, rather
173  than data+behaviour. If you need access control or are adding yet another
174  non-trivial (construction, assignment) member function to a `struct`,
175  just make it a `class` instead.
176* For newly created classes, keep to
177  [the rule of 3/5/0](http://en.cppreference.com/w/cpp/language/rule_of_three) -
178  make sure to read about the rule of zero if you haven't before, it's not
179  what you might think it is.
180* Qt containers are generally preferred to STL containers; however, there are
181  notable exceptions, and libQuotient already uses them:
182  * `std::array` and `std::deque` have no direct counterparts in Qt.
183  * Because of COW semantics, Qt containers cannot hold uncopyable classes.
184    Classes without a default constructor are a problem too. Examples of that
185    are `SyncRoomData` and `EventsArray<>`. Use STL containers for those but
186    see the next point and also consider if you can supply a reasonable
187    copy/default constructor.
188  * STL containers can be freely used in code internal to a translation unit
189    (i.e., in a certain .cpp file) _as long as that is not exposed in the API_.
190    It's ok to use, e.g., `std::vector` instead of `QVector` to tighten up
191    code where you don't need COW, or when dealing with uncopyable
192    data structures (see the previous point). However, exposing STL containers
193    in the API is not encouraged (except where absolutely necessary, e.g. we use
194    `std::deque` for a timeline). Exposing STL containers or iterators in API
195    intended for usage by QML code (e.g. in `Q_PROPERTY`) is unlikely to work
196    and therefore unlikely to be accepted into `master`.
197* Although `std::unique_ptr<>` gives slightly stronger guarantees,
198  `QScopedPointer<>` is better supported by Qt Creator's debugger UI and
199  therefore is preferred.
200* Use `QVector` instead of `QList` where possible - see the
201  [great article by Marc Mutz on Qt containers](https://marcmutz.wordpress.com/effective-qt/containers/)
202  for details.
203
204### API conventions
205
206Calls, data structures and other symbols not intended for use by clients
207should _not_ be exposed in (public) .h files, unless they are necessary
208to declare other public symbols. In particular, this involves private members
209(functions, typedefs, or variables) in public classes; use pimpl idiom to hide
210implementation details as much as possible. `_impl` namespace is reserved for
211definitions that should not be used by clients and are not covered by
212API guarantees.
213
214Note: As of now, all header files of libQuotient are considered public; this may change eventually.
215
216### Comments
217
218Whenever you add a new call to the library API that you expect to be used
219from client code, you must supply a proper doc-comment along with the call.
220Doxygen style is preferred; but JavaDoc is acceptable too. Some parts are
221not documented at all; adding doc-comments to them is highly encouraged.
222
223Doc-comments for summaries should be separate from those details. Either of
224the two following ways is fine, with considerable preference on the first one:
2251. Use `///` for the summary comment and `/*! ... */` for details.
2262. Use `\brief` (or `@brief`) for the summary, and follow with details after
227   an empty doc-comment line. You can use either of the delimiters in that case.
228
229In the code, the advice for commenting is as follows:
230* Don't restate what's happening in the code unless it's not really obvious.
231  We assume the readers to have at least some command of C++ and Qt. If your
232  code is not obvious, consider rewriting it for clarity.
233* Both C++ and Qt still come with their arcane features and dark corners,
234  and we don't want to limit anybody who'd feels they have a case for
235  variable templates, raw literals, or use `qAsConst` to avoid container
236  detachment. Use your experience to figure what might be less well-known to
237  readers and comment such cases (references to web pages, Quotient wiki etc.
238  are very much ok).
239* Make sure to document not so much "what" but more "why" certain code is done
240  the way it is. In the worst case, the logic of the code can be
241  reverse-engineered; you rarely can reverse-engineer the line of reasoning and
242  the pitfalls avoided.
243
244### Automated tests
245
246There's no testing framework as of now; either Catch or Qt Test or both will
247be used eventually.
248
249The `tests/` directory contains a command-line program, quotest, used for
250automated functional testing. Any significant addition to the library API
251should be accompanied by a respective test in quotest. To add a test you should:
252- Add a new test to the `TestSuite` class (technically, each test is a private
253  slot and there are two macros, `TEST_DECL()` and `TEST_IMPL()`, that conceal
254  passing the testing handle in `thisTest` variable to the test method).
255- Add test logic to the slot, using `FINISH_TEST` macro to assert the test
256  outcome and complete the test (`FINISH_TEST` contains `return`). ALL
257  (even failing) branches should conclude with a `FINISH_TEST` (or `FAIL_TEST`
258  that is a shortcut for a failing `FINISH_TEST`) invocation, unless you
259  intend to have a "DID NOT FINISH" message in the logs in certain conditions.
260
261The `TestManager` class sets up some basic test fixture to help you with testing;
262notably, the tests can rely on having an initialised `Room` object for the test
263room in `targetRoom` member variable. PRs to introduce a proper testing framework
264are very welcome (make sure to migrate tests from quotest though). Note that
265tests can go async, which is the biggest hurdle for Qt Test adoption.
266
267### Security, privacy, and performance
268
269Pay attention to security, and work *with* (not against) the usual security hardening mechanisms (however few in C++).
270
271`char *` and similar unchecked C-style read/write arrays are forbidden - use Qt containers or at the very least `std::array<>` instead. Where you see fit (usually with data structures), try to use smart pointers, especially `std::unique_ptr<>` or `QScopedPointer` instead of bare pointers. When dealing with `QObject`s, use the parent-child ownership semantics exercised by Qt (this is preferred to using smart pointers). Shared pointers are not used in the code so far; but if you find a particular use case where the strict semantic of unique pointers doesn't help and a shared pointer is necessary, feel free to step up with the working code and it will be considered for inclusion.
272
273Exercise the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) where reasonable and appropriate. Prefer less-coupled cohesive code.
274
275Protect private information, in particular passwords and email addresses. Absolutely _don't_ spill around this information in logs - use `access_token` and similar opaque ids instead, and only display those in UI where needed. Do not forget about local access to data (in particular, be very careful when storing something in temporary files, let alone permanent configuration or state). Avoid mechanisms that could be used for tracking where possible (we do need to verify people are logged in but that's pretty much it), and ensure that third parties can't use interactions for tracking. Matrix protocols evolve towards decoupling the personally identifiable information from user activity entirely - follow this trend.
276
277We want the software to have decent performance for typical users. At the same time we keep libQuotient single-threaded as much as possible, to keep the code simple. That means being cautious about operation complexity (read about big-O notation if you need a kickstart on the topic). This especially refers to operations on the whole timeline and the list of users - each of these can have tens of thousands of elements so even operations with linear complexity, if heavy enough, can produce noticeable GUI freezing. When you don't see a way to reduce algorithmic complexity, embed occasional `processEvents()` invocations in heavy loops (see `Connection::saveState()` to get the idea).
278
279Having said that, there's always a trade-off between various attributes; in particular, readability and maintainability of the code is more important than squeezing every bit out of that clumsy algorithm. Beware of premature optimization and have profiling data around before going into some hardcore optimization.
280
281Speaking of profiling logs (see README.md on how to turn them on) - in order
282to reduce small timespan logging spam, there's a default limit of at least
283200 microseconds to log most operations with the PROFILER
284(aka quotient.profile.debug) logging category. You can override this
285limit by passing the new value (in microseconds) in PROFILER_LOG_USECS to
286the compiler. In the future, this parameter will be made changeable at runtime
287_if_ needed.
288
289### Generated C++ code for CS API
290The code in lib/csapi, lib/identity and lib/application-service, although
291it resides in Git, is actually generated from (a soft fork of) the official
292Matrix Swagger/OpenAPI definition files. Do not edit C++ files
293in these directories by hand!
294
295Now, if you're unhappy with something in there and want to improve the code,
296you have to understand the way these files are produced and setup
297some additional tooling. The shortest possible procedure resembling
298the below text can be found in .travis.yml (our Travis CI configuration
299actually regenerates those files upon every build). As described below,
300there is a handy build target for CMake; patches with a similar target
301for qmake are (you guessed it) very welcome.
302
303#### Why generate the code at all?
304Because before both original authors of libQuotient had to do monkey business of writing boilerplate code, with the same patterns, types etc., literally, for every single API endpoint, and one of the authors got fed up with it at some point in time. By then about 15 job classes were written; the entire API counts about 100 endpoints. Besides, the existing jobs had to be updated according to changes in CS API that have been, and will keep, coming. Other considerations can be found in [this talk about API description languages that briefly touches on GTAD](https://youtu.be/W5TmRozH-rg).
305
306#### Prerequisites for CS API code generation
3071. Get the source code of GTAD and its dependencies, e.g. using the command:
308   `git clone --recursive https://github.com/KitsuneRal/gtad.git`
3092. Build GTAD: in the source code directory, do `cmake . && cmake --build .`
310   (you might need to pass `-DCMAKE_PREFIX_PATH=<path to Qt>`,
311   similar to libQuotient itself).
3123. Get the Matrix CS API definitions that are included in the matrix-doc repo:
313   `git clone https://github.com/quotient-im/matrix-doc.git`
314   (quotient-im/matrix-doc is a fork that's known to produce working code;
315   you may want to use your own fork if you wish to alter something in the API).
3164. If you plan to submit a PR or just would like the generated code to be
317   formatted, you should either ensure you have clang-format (version 6 at least)
318   in your PATH or pass the _absolute_ path to it by adding
319   `-DCLANG_FORMAT=<absolute path>` to the CMake invocation below.
320
321#### Generating CS API contents
3221. Pass additional configuration to CMake when configuring libQuotient:
323   `-DMATRIX_DOC_PATH=<path you your matrix-doc repo> -DGTAD_PATH=<path to gtad binary (not the repo!)>`.
324   If everything's right, these two CMake variables will be mentioned in
325   CMake output and will trigger configuration of an additional build target,
326   see the next step.
3272. Generate the code: `cmake --build <your build dir> --target update-api`;
328   if you use CMake with GNU Make, you can just do `make update-api` instead.
329   Building this target will create (overwriting without warning) `.h` and `.cpp`
330   files in `lib/csapi`, `lib/identity`, `lib/application-service` for all
331   YAML files it can find in `matrix-doc/api/client-server` and other files
332   in `matrix-doc/api` these depend on.
3333. Re-run CMake so that the build system knows about new files, if there are any.
334
335#### Changing generated code
336See the more detailed description of what GTAD is and how it works in the documentation on GTAD in its source repo. Only parts specific for libQuotient are described here.
337
338GTAD uses the following three kinds of sources:
3391. OpenAPI files. Each file is treated as a separate source (because this is how GTAD works now).
3402. A configuration file, in our case it's lib/csapi/gtad.yaml - this one is common for the whole API.
3413. Source code template files: lib/csapi/{{base}}.*.mustache - also common.
342
343The mustache files have a templated (not in C++ sense) definition of a network
344job, deriving from BaseJob; each job class is prepended, if necessary, with
345data structure definitions used by this job. The look of those files is hideous
346for a newcomer; and the only known highlighter that can handle the combination
347of Mustache (originally a web templating language) and C++ is provided in CLion.
348To slightly simplify things some more or less generic constructs are defined
349in gtad.yaml (see its "mustache:" section). Adventurous souls that would like
350to figure what's going on in these files should speak up in the Quotient room -
351I (Kitsune) will be very glad to help you out.
352
353The types map in `gtad.yaml` is the central switchboard when it comes to matching OpenAPI types with C++ (and Qt) ones. It uses the following type attributes aside from pretty obvious "imports:":
354* `avoidCopy` - this attribute defines whether a const ref should be used instead of a value. For basic types like int this is obviously unnecessary; but compound types like `QVector` should rather be taken by reference when possible.
355* `moveOnly` - some types are not copyable at all and must be moved instead (an obvious example is anything "tainted" with a member of type `std::unique_ptr<>`). The template will use `T&&` instead of `T` or `const T&` to pass such types around.
356* `useOmittable` - wrap types that have no value with "null" semantics (i.e. number types and custom-defined data structures) into a special `Omittable<>` template defined in `converters.h` - a substitute for `std::optional` from C++17 (we're still at C++14 yet).
357* `omittedValue` - an alternative for `useOmittable`, just provide a value used for an omitted parameter. This is used for bool parameters which normally are considered false if omitted (or they have an explicit default value, passed in the "official" GTAD's `defaultValue` variable).
358* `initializer` - this is a _partial_ (see GTAD and Mustache documentation for explanations but basically it's a variable that is a Mustache template itself) that specifies how exactly a default value should be passed to the parameter. E.g., the default value for a `QString` parameter is enclosed into `QStringLiteral`.
359
360Instead of relying on the event structure definition in the OpenAPI files, `gtad.yaml` uses pointers to libQuotient's event structures: `EventPtr`, `RoomEventPtr` and `StateEventPtr`. Respectively, arrays of events, when encountered in OpenAPI definitions, are converted to `Events`, `RoomEvents` and `StateEvents` containers. When there's no way to figure the type from the definition, an opaque `QJsonObject` is used, leaving the conversion to the library and/or client code.
361
362## How to check proposed changes before submitting them
363
364Checking the code on at least one configuration is essential; if you only have
365a hasty fix that doesn't even compile, better make an issue and put a link to
366your commit into it (with an explanation what it is about and why).
367
368### Standard checks
369
370The following warnings configuration is applied with GCC and Clang when using CMake:
371`-W -Wall -Wextra -pedantic -Werror=return-type -Wno-unused-parameter -Wno-gnu-zero-variadic-macro-arguments`
372(the last one is to mute a warning triggered by Qt code for debug logging).
373We don't turn most of the warnings to errors but please treat them as such.
374If you use Qt Creator, the following line can be used with the Clang code model:
375`-Weverything -Werror=return-type -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-newline-eof -Wno-exit-time-destructors -Wno-global-constructors -Wno-gnu-zero-variadic-macro-arguments -Wno-documentation -Wno-missing-prototypes -Wno-shadow-field-in-constructor -Wno-padded -Wno-weak-vtables -Wno-unknown-attributes -Wno-comma`.
376
377### Continuous Integration
378
379We use Travis CI to check buildability and smoke-testing on Linux (GCC, Clang) and MacOS (Clang), and AppVeyor CI to build on Windows (MSVC). Every PR will go through these, and you'll see the traffic lights from them on the PR page. If your PR fails on any platform double-check that it's not your code causing it - and fix it if it is.
380
381### clang-format
382
383We strongly recommend using clang-format or, even better, use an IDE that
384supports it. This will lay a tedious task of following the assumed
385code style from your shoulders over to your computer.
386
387### Other tools
388
389Recent versions of Qt Creator and CLion can automatically run your code through
390clang-tidy. The following list of clang-tidy checks slows Qt Creator analysis
391quite considerably but gives a good insight without too many false positives:
392`-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bool-pointer-implicit-conversion,bugprone-copy-constructor-init,bugprone-dangling-handle,bugprone-fold-init-type,bugprone-forward-declaration-namespace,bugprone-inaccurate-erase,bugprone-integer-division,bugprone-move-forwarding-reference,bugprone-string-constructor,bugprone-undefined-memory-manipulation,bugprone-use-after-move,bugprone-virtual-near-miss,cert-dcl03-c,cert-dcl21-cpp,cert-dcl50-cpp,cert-dcl54-cpp,cert-dcl58-cpp,cert-env33-c,cert-err09-cpp,cert-err34-c,cert-err52-cpp,cert-err60-cpp,cert-err61-cpp,cert-fio38-c,cert-flp30-c,cert-msc30-c,cert-msc50-cpp,cert-oop11-cpp,cppcoreguidelines-c-copy-assignment-signature,cppcoreguidelines-pro-type-cstyle-cast,cppcoreguidelines-slicing,hicpp-deprecated-headers,hicpp-invalid-access-moved,hicpp-member-init,hicpp-move-const-arg,hicpp-named-parameter,hicpp-new-delete-operators,hicpp-static-assert,hicpp-undelegated-constructor,hicpp-use-*,misc-misplaced-const,misc-new-delete-overloads,misc-non-copyable-objects,misc-redundant-expression,misc-static-assert,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,misc-uniqueptr-reset-release,misc-unused-*,modernize-loop-convert,modernize-pass-by-value,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-*,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-*,performance-move-*,performance-type-promotion-in-math-fn,performance-unnecessary-*,readability-delete-null-pointer,readability-else-after-return,readability-inconsistent-declaration-parameter-name,readability-misleading-indentation,readability-redundant-*,readability-simplify-boolean-expr,readability-static-definition-in-anonymous-namespace,readability-uniqueptr-delete-release`.
393
394Qt Creator, in addition, knows about clazy, an even deeper Qt-aware static
395analysis tool. Even level 1 clazy eats away CPU but produces some very relevant
396notices that are easy to overlook otherwise, such as possible unintended copying
397of a Qt container, or unguarded null pointers. You can use this time to time
398(see Analyze menu in Qt Creator) instead of hogging your machine with
399deep analysis as you type.
400
401## Git commit messages
402
403When writing git commit messages, try to follow the guidelines in
404[How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/):
405
4061.  Separate subject from body with a blank line
4072.  Be reasonable on the subject line length, because this is what we see in commit logs. Try to fit in 50 characters whenever possible.
4083.  Capitalize the subject line
4094.  Do not end the subject line with a period
4105.  Use the imperative mood in the subject line (*command* form)
411  (we don't always practice this ourselves but let's try).
4126.  Use the body to explain what and why vs. how
413    (git tracks how it was changed in detail, don't repeat that). Sometimes a quick overview of "how" is acceptable if a commit is huge - but maybe split a commit into smaller ones, to begin with?
414
415## Reuse (libraries, frameworks, etc.)
416
417C++ is unfortunately not very coherent about SDK/package management, and we try to keep building the library as easy as possible. Because of that we are very conservative about adding dependencies to libQuotient. That relates to additional Qt components and even more to other libraries. Fortunately, even the Qt components now in use (Qt Core and Network) are very feature-rich and provide plenty of ready-made stuff.
418
419Regardless of the above paragraph (and as mentioned earlier in the text), we're now looking at possible options for futures and automated testing, so PRs onboarding those will be considered with much gratitude.
420
421Some cases need additional explanation:
422* Before rolling out your own super-optimised container or algorithm written
423  from scratch, take a good long look through documentation on Qt and
424  C++ standard library. Please try to reuse the existing facilities
425  as much as possible.
426* You should have a good reason (or better several ones) to add a component
427  from KDE Frameworks. We don't rule this out and there's no prejudice against
428  KDE; it just so happened that KDE Frameworks is one of most obvious
429  reuse candidates but so far none of these components survived
430  as libQuotient deps. So we are cautious. Extra notice to KDE folks:
431  I'll be happy if an addon library on top of libQuotient is made using
432  KDE facilities, and I'm willing to take part in its evolution; but please
433  also respect LXDE people who normally don't have KDE frameworks installed.
434* Never forget that libQuotient is aimed to be a non-visual library;
435  QtGui in dependencies is only driven by (entirely offscreen) dealing with
436  QImages. While there's a bunch of visual code (in C++ and QML) shared
437  between Quotient-enabled _applications_, this is likely to end up
438  in a separate (Quotient-enabled) library, rather than libQuotient itself.
439
440## Attribution
441
442This text is based on CONTRIBUTING.md from CII Best Practices Badge project, which is a collective work of its contributors (many thanks!). The text itself is licensed under CC-BY-4.0.
443