Tip of the day: Almost every channel mode can be disabled. Don't like halfops? Use blacklist-module chanmodes/halfop;

Dev:Coding guidelines

From UnrealIRCd documentation wiki
Jump to navigation Jump to search

This article describes how code for UnrealIRCd should be written and committed. See Contributing for the process around it, such as: reporting bugs, discussing changes, submitting patches.

Code style

Code formatting

Code formatting is fully automated. The rules live in the .clang-format file in the source and you apply them by running make format (this requires clang-format major version 21). The easiest way is to let your editor format on save, see Dev:Visual Studio Code. Pull requests containing unformatted code will be rejected by the CI.

A few things are deliberately not auto-formatted: hand-formatted tables and similar are surrounded by /* clang-format off */ and /* clang-format on */ markers. Only use these markers when manual layout genuinely is more readable, such as in large data tables.

Git pre-commit hook

Developers with commit access are assumed to have a git pre-commit hook that refuses unformatted code. Save the following as .git/hooks/pre-commit and make it executable (chmod +x):

#!/bin/sh
# Check-only hook: refuse to commit code that is not clang-formatted.
# Never modifies anything. Bypass once with: git commit --no-verify
output=$(git clang-format --staged --diff 2>/dev/null)
case "$output" in
	""|"no modified files to format"*|"clang-format did not modify any files"*)
		exit 0
		;;
	*)
		echo "ERROR: Commit rejected: staged changes are not clang-formatted."
		echo "Run 'make format', review the result, and commit again."
		echo "(Bypass once with: git commit --no-verify)"
		exit 1
		;;
esac

This requires git-clang-format, which comes with clang-format on most distributions.

Again, you should use clang version 21 here. If you have multiple clang versions installed, then tell it which one to use with: git config clangFormat.binary clang-format-21

Major restructuring or cleanups

If you want to restructure or clean up existing code beyond a bug or isolated feature you are working on, then you MUST discuss it first. The stable tree is often not really suitable for such things, especially if we are talking multiple files etc.

Also be careful with cleanups in general: if something looks redundant or useless at first sight, look again. It may indeed be useless, but it may also be a subtle thing that creates great bugs when 'cleaned up'.

Comments

Comment your code. It will help the next person reading it, and it will help you when you look at your own code two years later. If there is some obscure pitfall in the code, then DO mention it. Don't just hope the next author will see it like you did.

For documenting functions and struct members we use doxygen style comments: /** Like this */. Regular comments use /* this style */. Using // is acceptable for a short single-line remark, but multi-line comments always use /* */. Don't mass-convert comments from one style to the other.

Writing good code

String handling

Be careful about overflows, do not do any unchecked string copies. Instead of strcpy, strcat and sprintf, use the length-checking functions: strlcpy, strlcat and snprintf/ircsnprintf. If you are copying or writing character-by-character in a loop, for example using *p++ = x;, then be very sure about your size counting. Often it is better to avoid such code altogether and simply use strlcat and similar functions for everything.

Memory

Use safe_alloc, safe_free, safe_strdup and safe_strldup. These functions properly initialize memory (such as structs) with zeroes.

Do NOT use malloc, calloc, free or strdup directly.

Logging

All (new) code uses unreal_log() for logging and server notices (snomasks, etc). Don't use legacy calls. Exceptions are config_warn/config_error in config code.

Readability comes first

When writing or optimizing code, readability and stability come FIRST, speed comes after that.

We prefer readable code over a highly optimized routine that nobody understands, is difficult to extend, and might have several bugs.

Portability

The minimum is a C99 compiler, which ./configure enforces. In practice the code is built as C17 with GNU extensions on *NIX.

Code must also compile on Windows with Visual Studio 2019, so don't use exotic compiler-specific extensions.

Enums

  • Use enums rather than #define constants whenever possible. It is cleaner and it aids debugging. For bit flags, we still use defines.

Before you commit

Test your code

Very important: TEST your code before committing or doing a Pull Request. Not just that it compiles, but also that it does what you want. Yes, also that one line change that you are 100% sure about breaks nothing :-)

There is also a test suite which the CI runs on every push and pull request.

Copyright

  • New files must contain a proper copyright header. UnrealIRCd is GNU GPLv2 or later, so it must be compatible.
  • If code from other people or projects is used, it MUST be properly credited (and again, the license must permit it).

Security issues

If you found a security issue, then do NOT report or discuss it on the public bug tracker. See Policy: Handling of security issues for how to report it privately.

Developers with commit access

The following applies to developers who commit directly to the repository, including when merging someone else's pull request.

Changes that need prior discussion

The rules about discussing changes from Contributing apply to developers with commit access as well. Especially since commits go in directly, without any reviews or way to stop it prior.

Before starting on anything big, make sure there is a bugtracker entry for it and that it has been discussed or acknowledged. Same for protocol changes or major code restructuring, breaking module API, etc.

Commit messages

The following applies to commits from yourself and if you merge someones PR:

  • The first line of the commit message is a short summary of max 70 characters. This is what GitHub and git log --oneline show in commit overviews, so it must make sense on its own.
  • The rest of the commit message should explain what you changed and why.
  • If there is a related item on bugs.unrealircd.org you end the commit message with:
    Reported by XYZ in https://bugs.unrealircd.org/view.php?id=####
    It is important to credit people: they have taken the time to report an issue/feature so they deserve credit.

After committing

If the commit relates to a bug# on bugs.unrealircd.org:

  • Mark the issue as 'Resolved' and set the 'Fixed in version' to the future release
  • In the comment on the bug tracker copy-paste the commit reference: at least the github URL to the commit, but preferably the copy-paste of 'git log' that is relevant

Version files

Do not touch version.c.SH or version.h. Those are for the head coders, as part of doing releases.