style.rst (20325B)
1 .. _dev-style-workflow: 2 3 ******************* 4 Style and Workflow 5 ******************* 6 7 This document contains normative rules for writing GNUnet 8 code and naming conventions used throughout the project. 9 10 Coding style 11 ============ 12 13 This project follows the GNU Coding Standards. 14 15 Indentation is done with two spaces per level, never with tabs. 16 Specific (though incomplete) indentation rules are defined in an ``uncrustify`` 17 configuration file (in ``contrib/uncrustify.cfg``) and are enforced by Git hooks. 18 19 C99-style struct initialisation is acceptable and generally encouraged. 20 21 As in all good C code, we care about symbol space pollution and thus use 22 :code:`static` to limit the scope where possible, even in the compilation 23 unit that contains :code:`main`. 24 25 Only one variable should be declared per line: 26 27 .. code-block:: c 28 29 // bad 30 int i,j; 31 32 // good 33 int i; 34 int j; 35 36 This helps keep diffs small and forces developers to think precisely about 37 the type of every variable. 38 39 Note that :c:`char *` is different from :c:`const char*` and 40 :c:`int` is different from :c:`unsigned int` or :c:`uint32_t`. 41 Each variable type should be chosen with care. 42 43 44 While ``goto`` should generally be avoided, having a ``goto`` to the 45 end of a function to a block of clean up statements (free, close, 46 etc.) can be acceptable. 47 48 Conditions should be written with constants on the left (to avoid 49 accidental assignment) and with the ``true`` target being either the 50 ``error`` case or the significantly simpler continuation. For 51 example: 52 53 :: 54 55 if (0 != stat ("filename," 56 &sbuf)) 57 { 58 error(); 59 } 60 else 61 { 62 /* handle normal case here */ 63 } 64 65 instead of 66 67 :: 68 69 if (stat ("filename," &sbuf) == 0) { 70 /* handle normal case here */ 71 } else { 72 error(); 73 } 74 75 If possible, the error clause should be terminated with a ``return`` 76 (or ``goto`` to some cleanup routine) and in this case, the ``else`` 77 clause should be omitted: 78 79 :: 80 81 if (0 != stat ("filename", 82 &sbuf)) 83 { 84 error(); 85 return; 86 } 87 /* handle normal case here */ 88 89 This serves to avoid deep nesting. The 'constants on the left' rule 90 applies to all constants (including. ``GNUNET_SCHEDULER_NO_TASK``), 91 NULL, and enums). With the two above rules (constants on left, errors 92 in 'true' branch), there is only one way to write most branches 93 correctly. 94 95 Combined assignments and tests are allowed if they do not hinder code 96 clarity. For example, one can write: 97 98 :: 99 100 if (NULL == (value = lookup_function())) 101 { 102 error(); 103 return; 104 } 105 106 Use ``break`` and ``continue`` wherever possible to avoid deep(er) 107 nesting. Thus, we would write: 108 109 :: 110 111 next = head; 112 while (NULL != (pos = next)) 113 { 114 next = pos->next; 115 if (! should_free (pos)) 116 continue; 117 GNUNET_CONTAINER_DLL_remove (head, 118 tail, 119 pos); 120 GNUNET_free (pos); 121 } 122 123 instead of 124 125 :: 126 127 next = head; while (NULL != (pos = next)) { 128 next = pos->next; 129 if (should_free (pos)) { 130 /* unnecessary nesting! */ 131 GNUNET_CONTAINER_DLL_remove (head, tail, pos); 132 GNUNET_free (pos); 133 } 134 } 135 136 We primarily use ``for`` and ``while`` loops. A ``while`` loop is 137 used if the method for advancing in the loop is not a straightforward 138 increment operation. In particular, we use: 139 140 :: 141 142 next = head; 143 while (NULL != (pos = next)) 144 { 145 next = pos->next; 146 if (! should_free (pos)) 147 continue; 148 GNUNET_CONTAINER_DLL_remove (head, 149 tail, 150 pos); 151 GNUNET_free (pos); 152 } 153 154 to free entries in a list (as the iteration changes the structure of 155 the list due to the free; the equivalent ``for`` loop does no longer 156 follow the simple ``for`` paradigm of ``for(INIT;TEST;INC)``). 157 However, for loops that do follow the simple ``for`` paradigm we do 158 use ``for``, even if it involves linked lists: 159 160 :: 161 162 /* simple iteration over a linked list */ 163 for (pos = head; 164 NULL != pos; 165 pos = pos->next) 166 { 167 use (pos); 168 } 169 170 The first argument to all higher-order functions in GNUnet must be 171 declared to be of type ``void *`` and is reserved for a closure. We 172 do not use inner functions, as trampolines would conflict with setups 173 that use non-executable stacks. The first statement in a higher-order 174 function, which unusually should be part of the variable 175 declarations, should assign the ``cls`` argument to the precise 176 expected type. For example: 177 178 :: 179 180 int 181 callback (void *cls, 182 char *args) 183 { 184 struct Foo *foo = cls; 185 int other_variables; 186 187 /* rest of function */ 188 } 189 190 As shown in the example above, after the return type of a function 191 there should be a break. Each parameter should be on a new line. 192 193 It is good practice to write complex ``if`` expressions instead of 194 using deeply nested ``if`` statements. However, except for addition 195 and multiplication, all operators should use parens. This is fine: 196 197 :: 198 199 if ( (1 == foo) || 200 ( (0 == bar) && 201 (x != y) ) ) 202 return x; 203 204 However, this is not: 205 206 :: 207 208 if (1 == foo) 209 return x; 210 if (0 == bar && x != y) 211 return x; 212 213 Note that splitting the ``if`` statement above is debatable as the 214 ``return x`` is a very trivial statement. However, once the logic 215 after the branch becomes more complicated (and is still identical), 216 the \"or\" formulation should be used for sure. 217 218 There should be two empty lines between the end of the function and 219 the comments describing the following function. There should be a 220 single empty line after the initial variable declarations of a 221 function. If a function has no local variables, there should be no 222 initial empty line. If a long function consists of several complex 223 steps, those steps might be separated by an empty line (possibly 224 followed by a comment describing the following step). The code should 225 not contain empty lines in arbitrary places; if in doubt, it is 226 likely better to NOT have an empty line (this way, more code will fit 227 on the screen). 228 229 When command-line arguments become too long (and would result in some 230 particularly ugly ``uncrustify`` wrapping), we start all arguments on 231 a new line. As a result, there must never be a new line within an 232 argument declaration (i.e. between ``struct`` and the struct's name) 233 or between the type and the variable). Example: 234 235 :: 236 237 struct GNUNET_TRANSPORT_CommunicatorHandle * 238 GNUNET_TRANSPORT_communicator_connect ( 239 const struct GNUNET_CONFIGURATION_Handle *cfg, 240 const char *config_section_name, 241 const char *addr_prefix, 242 ...); 243 244 Note that for short function names and arguments, the first argument 245 does remain on the same line. Example: 246 247 :: 248 249 void 250 fun (short i, 251 short j); 252 253 254 Naming conventions 255 ================== 256 257 Header files 258 ------------ 259 .. Not sure if "include" and "header" files are synonymous. 260 261 262 For header files, the following suffixes should be used: 263 264 ============= ====================================== 265 Suffix Usage 266 ============= ====================================== 267 ``_lib`` Libraries without associated processes 268 ``_service`` Libraries using service processes 269 ``_plugin`` Plugin definition 270 ``_protocol`` structs used in network protocol 271 ============= ====================================== 272 273 There exist a few exceptions to these rules within the codebase: 274 275 * ``gnunet_config.h`` is automatically generated. 276 * ``gnunet_common.h``, which defines fundamental routines. 277 * ``platform.h``, a collection of portability functions and macros. 278 * ``gettext.h``, the internationalization configuration for gettext in GNUnet. 279 280 281 Binaries 282 -------- 283 284 For binary files, the following convention should be used: 285 286 =============================== ========================================= 287 Name format Usage 288 =============================== ========================================= 289 ``gnunet-service-xxx`` Service processes (with listen sockets) 290 ``gnunet-daemon-xxx`` Daemon processes (without listen sockets) 291 ``gnunet-helper-xxx[-yyy]`` SUID helper for module xxx 292 ``gnunet-yyy`` End-user command line tools 293 ``libgnunet_plugin_xxx_yyy.so`` Plugin for API xxx 294 ``libgnunetxxx.so`` Library for API xxx 295 =============================== ========================================= 296 297 Logging 298 ------- 299 300 The convention is to define a macro on a per-file basis to manage logging: 301 302 .. code-block:: c 303 304 #define LOG(kind,...) 305 [logging_macro] (kind, "[component_name]", __VA_ARGS__) 306 307 The table below indicates the substitutions which should be made 308 for ``[component_name]`` and ``[logging_macro]``. 309 310 ======================== ========================================= =================== 311 Software category ``[component_name]`` ``[logging_macro]`` 312 ======================== ========================================= =================== 313 Services and daemons Directory name in ``GNUNET_log_setup`` ``GNUNET_log`` 314 Command line tools Full name in ``GNUNET_log_setup`` ``GNUNET_log`` 315 Service access libraries ``[directory_name]`` ``GNUNET_log_from`` 316 Pure libraries Library name (without ``lib`` or ``.so``) ``GNUNET_log_from`` 317 Plugins ``[directory_name]-[plugin_name]`` ``GNUNET_log_from`` 318 ======================== ========================================= =================== 319 320 .. todo:: Clear up terminology within the style guide (_lib, _service mapped to appropriate software categories) 321 322 .. todo:: Interpret and write configuration style 323 324 Symbols 325 ------- 326 327 Exported symbols must be prefixed with ``GNUNET_[module_name]_`` and be 328 defined in ``[module_name].c``. There are exceptions to this rule such as 329 symbols defined in ``gnunet_common.h``. 330 331 Private symbols, including ``struct``\ s and macros, must not be prefixed. 332 In addition, they must not be exported in a way that linkers could use them 333 or other libraries might see them via headers. This means that they must 334 **never** be declared in ``src/include``, and only declared or defined in 335 C source files or headers under ``src/[module_name]``. 336 337 338 Tests 339 ----- 340 341 In the core of GNUnet, we restrict new testcases to a small subset of 342 languages, in order of preference: 343 344 1. C 345 346 2. Portable Shell Scripts 347 348 3. Python (3.7 or later) 349 350 We welcome efforts to remove our existing Python 2.7 scripts to replace 351 them either with portable shell scripts or, at your choice, Python 3.7 352 or later. 353 354 If you contribute new python based testcases, we advise you to not 355 repeat our past misfortunes and write the tests in a standard test 356 framework like for example pytest. 357 358 For writing portable shell scripts, these tools are useful: 359 360 * `Shellcheck <https://github.com/koalaman/shellcheck>`__, for static 361 analysis of shell scripts. 362 * http://www.etalabs.net/sh_tricks.html, 363 * ``bash``-``dash`` (``/bin/sh`` on Debian) interoperability 364 * `checkbashisms <https://salsa.debian.org/debian/devscripts/blob/master/scripts/checkbashisms.pl>`__, 365 * https://wiki.ubuntu.com/DashAsBinSh, and 366 * https://mywiki.wooledge.org/Bashism 367 368 Test cases and performance tests should follow the naming conventions 369 ``test_[module-under-test]_[test_description].c`` and 370 ``perf_[module-under-test]_[test_description].c``, respectively. 371 372 In either case, if there is only a single test, ``[test_description]`` 373 may be omitted. 374 375 376 377 Continuous integration 378 ====================== 379 380 The continuous integration buildbot can be found at 381 https://buildbot.gnunet.org. Repositories need to be enabled by a 382 buildbot admin in order to participate in the builds. 383 384 The buildbot can be configured to process scripts in your repository 385 root under ``.buildbot/``: 386 387 The files ``build.sh``, ``install.sh`` and ``test.sh`` are executed in 388 order if present. If you want a specific worker to behave differently, 389 you can provide a worker specific script, e.g. ``myworker_build.sh``. In 390 this case, the generic step will not be executed. 391 392 For the ``gnunet.git`` repository, you may use \"!tarball\" or 393 \"!coverity\" in your commit messages. \"!tarball\" will trigger a 394 ``make dist`` of the gnunet source and verify that it can be compiled. 395 The artifact will then be published to 396 https://buildbot.gnunet.org/artifacts. This is a good way to create a 397 tarball for a release as it verifies the build on another machine. 398 399 The \"!coverity\" trigger will trigger a coverity build and submit the 400 results for analysis to coverity: https://scan.coverity.com/. Only 401 developers with accounts for the GNUnet project on coverity.com are able 402 to see the analysis results. 403 404 405 Developer access and commit messages 406 ==================================== 407 408 Major changes **SHOULD** be developed in a developer branch. 409 A developer branch is a branch which matches a developer-specific 410 prefix. As a developer with git access, you should have a git username. 411 If you do not know it, please ask an admin. A developer branch has the 412 format: 413 414 :: 415 416 dev/<username>/<branchname> 417 418 Assuming the developer with username \"jdoe\" wants to create a new 419 branch for an i18n fix, the branch name could be: 420 421 :: 422 423 dev/jdoe/i18n_fx 424 425 You will be able to force push to and delete branches under 426 your prefix. It is highly recommended to work in your own developer 427 branches. 428 Most developers only have access to developer branches anyway. 429 Code which conforms to the commit message guidelines and 430 coding style, is tested and builds may be merged to the master branch. 431 Preferably, you would then\... 432 433 - (optional) \...squash your commits, 434 435 - rebase to master and then 436 437 - ask that your branch is merged into master. 438 439 - (optional) Delete the branch. 440 441 In general, you may want to follow the rule \"commit often, push tidy\": 442 You can create smaller, succinct commits with limited meaning on the 443 commit messages. In the end and before you push or ask your branch to be 444 merged, you can then squash the commits or rename them. 445 You can ask the project maintainer to merge your branch through any channel, 446 but the gnunet-developers@gnu.org mailing list is the preferred method. 447 448 Commit messages are required to convey what changes were 449 made in a self-contained fashion. Commit messages such as \"fix\" or 450 \"cleanup\" are not acceptable. You commit message should ideally start 451 with the subsystem name and be followed by a succinct description of the 452 change. Where applicable a reference to a bug number in the bugtracker 453 may also be included. Example: 454 455 .. code-block:: text 456 457 # <subsystem>: <description>. (#XXXX) 458 IDENTITY: Fix wrong key construction for anonymous ECDSA identity. (Fixes #12344) 459 460 We do not maintain a separate ChangeLog file anymore as the changes are 461 documented in the git repositories. 462 If you edit files that change user-facing behaviour (e.g. header files in src/include) 463 you will have to add at least one line in the commit message starting with \"NEWS:\". 464 If there is a special reason why you deem this unnecessary, you can add the line 465 \"NEWS: -\". 466 Any \"NEWS\" lines from commit messages will on release be put into the "NEWS" file in the tarball 467 to inform users and packages of noteworthy changes. 468 469 .. code-block:: text 470 471 # NEWS 472 NEWS: The API for foo has changed: lorem ipsum. 473 474 Note that if you run \"./bootstrap\" hooks will be installed that add message hints 475 to your commit message template when you run \"git commit\". 476 477 If you need to modify a commit you can do so using: 478 479 .. code-block:: console 480 481 $ git commit --amend 482 483 If you need to modify a number of successive commits you will have to 484 rebase and squash. Note that most branches are protected. This means 485 that you can only fix commits as long as they are not pushed. You can 486 only modify pushed commits in your own developer branches. 487 488 489 490 491 Releases 492 ======== 493 494 Packaging a release can only be done by a maintainer. 495 496 In this order do: 497 498 0. Update your local tree 499 500 1. Update the submodule ``contrib/handbook`` 501 502 2. Run ``./bootstrap`` to regenerate files 503 504 3. *Optional*: Update bootstrap HELLO file and update GANA generated files using ``./scripts/gana_update.sh`` 505 506 4. Update NEWS file and PO files and commit 507 508 5. Tag the release (Named commit!) 509 510 6. Create and test tarballs 511 512 7. Upload tarball 513 514 8. Write release announcement 515 516 517 **(1)** Make sure the ``contrib/handbook`` submodule 518 is up to date. 519 In the **handbook repository**, make sure you have a folder that 520 contains the ``prebuilt`` branch as a worktree: 521 522 .. code-block:: console 523 524 $ git worktree add _build prebuilt 525 526 Then compile the current handbook: 527 528 .. code-block:: console 529 530 $ sphinx-multiversion --dump-metadata . _build 531 532 Commit the changes (if any) and update the submoduce in the 533 gnunet repository under ``doc/handbook`` and execute: 534 535 .. code-block:: console 536 537 $ git pull origin prebuilt 538 539 If the submodule was updated, commit the new submodule. 540 541 **(2)** You should now re-run bootstrap:: 542 543 .. code-block:: console 544 545 $ ./bootstrap 546 547 **(3)** If this is a major release, it makes sense to update the bootstrap peer 548 549 HELLO. For this, you need access to the bootstrap peer (``GKZS``) and create 550 the hello file. Make sure that you update the bootstrap peer first such that 551 any changes in the identity format are actually refrected! 552 It is recommended to have it expire within a year: 553 554 .. code-block:: console 555 556 $ gnunet-hello -e -E "1 year" -b -c gnunet.conf > GKZSYTE4H3N4RMYGFYEM95RV1CDRPH8QNJNTPMEB7C4QJGGR3KEG 557 558 You can then update the file in ``data/hellos``. 559 560 **(4)** Then, in order to pre-populate the news file with news hints 561 from commit messages (see above), we execute 562 563 .. code-block:: console 564 565 $ sh contrib/scripts/update_news.sh v0.22.0 566 567 ``v0.22.0`` is the placeholder for the version number you want to release. 568 Now edit the ``NEWS`` file to include all the noteworthy changes 569 you want to add. 570 571 Then, update the po files: 572 573 .. code-block:: console 574 575 $ meson setup build-release && meson compile -C build-release gnunet-update-po 576 577 Commit all changes in the source tree now, and push the changes. 578 579 **(5)** You can now tag the release. Please **always** use named tags (important for our 580 nightly tarball build trigger). 581 582 .. code-block:: console 583 584 $ git tag v0.22.0 -m "GNUnet release v0.22.0" 585 586 **(6)** Then, we can re-run ``./bootstrap`` and make the tarball: 587 588 .. code-block:: console 589 590 $ ./bootstrap && meson setup --reconfigure build-release && meson dist -C build-release --formats gztar 591 592 593 Meson will automatically run the tests. 594 595 **(7)** To distribute the tarballs create a release triplet as defined in the GNU guidelines and 596 upload them to the FTP (https://www.gnu.org/prep//maintain/html_node/Automated-FTP-Uploads.html). 597 598 The file ``gnunet-0.22.0.tar.gz`` will be found inside ``build/meson-dist``. 599 The file must be signed by a maintainer and the signature and tarball uploaded to 600 https://buildbot.gnunet.org/releases/. 601 602 **(8)** After the tarballs are uploaded, we need to write the announcement. 603 For minor releases, we only write a brief statement: 604 605 .. code-block:: text 606 607 See also: https://www.gnunet.org/en/news/2024-06-0.21.2.html 608 609 This is a bugfix release for gnunet 0.21.1. It primarily addresses some 610 connectivity issues introduced with our new transport subsystem. 611 612 Links 613 614 Source: https://ftpmirror.gnu.org/gnunet/gnunet-0.21.2.tar.gz (https://ftpmirror.gnu.org/gnunet/gnunet-0.21.2.tar.gz.sig) 615 Detailed list of changes: https://git.gnunet.org/gnunet.git/log/?h=v0.21.2 616 NEWS: https://git.gnunet.org/gnunet.git/tree/NEWS?h=v0.21.2 617 The list of closed issues in the bug tracker: https://bugs.gnunet.org/changelog_page.php?version_id=440 618 619 The GPG key used to sign is: 3D11063C10F98D14BD24D1470B0998EF86F59B6A 620 621 Note that due to mirror synchronization, not all links may be 622 functional early after the release. For direct access try 623 https://ftp.gnu.org/gnu/gnunet/ 624 625 The announcement is posted to ``gnunet-developers@gnu.org`` as well as 626 ``help-gnunet@gnu.org``. 627 628 For major releases, we use a full release announcement. 629 You can find the template in the ``www.git``. 630 The full release announcement is sent to 631 ``info-gnu@gnu.org`` as well.