diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 18f46cd998e..163fca7033e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,7 +9,11 @@ These points need to be fulfilled for every PR: - [ ] Details of what you changed are in commit messages (first line should have `module: short statement` syntax) - [ ] References to issues, e.g. `close #X`, are in the commit messages. -- [ ] The buildservers are happy. +- [ ] The buildservers are happy. If not, fix **in this order**: + - [ ] add a line in `doc/news/_preparation_next_release.md` + - [ ] reformat the code with `scripts/dev/reformat-all` + - [ ] make all unit tests pass + - [ ] fix all memleaks - [ ] The PR is rebased with current master. If you have any troubles fulfilling these criteria, please write diff --git a/README.md b/README.md index aad6c4cac67..9b3cf71b974 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ applications' configurations, leveraging easy application integration. ## Often Used Links +- If you are new, start reading [Get Started](doc/GETSTARTED.md) - [Build server](https://build.libelektra.org/) - [Website](https://www.libelektra.org) - [API documentation](https://doc.libelektra.org/api/latest/html/) diff --git a/doc/GETSTARTED.md b/doc/GETSTARTED.md index 8200abd0e5d..7c0e2f7535e 100644 --- a/doc/GETSTARTED.md +++ b/doc/GETSTARTED.md @@ -59,10 +59,15 @@ cmake .. # watch output to see if everything needed is included # optionally run "ccmake .." to get an overview of the available build settings (needs cmake-curses-gui) cmake --build build -- -j5 - cmake --build build --target run_nokdbtests #optional: run tests ``` - With these commands you will be able to run the "Hello World!" example but usually you will need to use some of the [plugins](/src/plugins/README.md), tools and bindings of Elektra. Please take a look to the more detailed [compiling documentation](/doc/COMPILE.md). After you completed building Elektra on your own, you can execute these commands to install Elektra (please check the [installation documentation](/doc/INSTALL.md) if you are using Debian): + Optionally you can also run tests, see [here for more information](/doc/TESTING.md): + + ```sh + cmake --build build --target run_nokdbtests + ``` + + With these commands you will be able to run the "Hello World!" example but usually you will need to use some of the [plugins](/src/plugins/README.md), tools and bindings of Elektra. Please take a look at the more detailed [compiling documentation](/doc/COMPILE.md). After you completed building Elektra on your own, you can execute these commands to install Elektra (please check the [installation documentation](/doc/INSTALL.md) for the many available packages): ```sh sudo make install @@ -71,7 +76,13 @@ [Installation documentation](/doc/INSTALL.md) contains further information about available packages. + Optionally you can also run tests to verify the installed Elektra, see [here for more information](/doc/TESTING.md): + + ```sh + kdb run_nokdbtests + ``` + - Hello World! - Start with your very first Elektra application and follow these steps: + Start with your very first Elektra application in C and follow these steps: [Hello World!](/doc/tutorials/hello-elektra.md) diff --git a/doc/METADATA.ini b/doc/METADATA.ini index 71852fb5707..1d1c7161e51 100644 --- a/doc/METADATA.ini +++ b/doc/METADATA.ini @@ -59,7 +59,7 @@ version/minor=6 # # Important metadata often used in configuration files -# (and seldom in specifications) +# and not used in specifications. # [order] @@ -153,14 +153,18 @@ description= The spaces/tabs used between a comment and the beginning of the example= - - -[line] -type= int -status= proposal -description= contains the line number from which a key was read. -note= is useful for validation problems when someone directly - edits files +[internal//*] +status= implemented +usedby/plugin= +description= Internal metadata that must be ignored by other plugins. + It is useful for reconstruction of information about keys between + kdbGet and kdbSet. + Always avoid to use it if there is any other metadata that + can be used instead. + For example, if a type can be represented with the CORBA + type system, metadata `type` should be used. + Only if a type cannot be represented, e.g., the `toml` + plugin would use `internal/toml/type`. @@ -255,7 +259,7 @@ description= For this metadata only the presence is significant, not its value. [array] type= array-index -status= proposed +status= implemented description= Such keys have only keys conforming to Elektra’s arrays convention as subkeys. If the metavalue is empty, the array is empty (no subkeys). Otherwise the metavalue contains the last element. @@ -300,9 +304,9 @@ note= It is generally preferred that other metadata will be used to deduce the needs of the specification, e.g. use check/validation metadata instead of as given above. -[config] +[config/needs] type= string -status= proposed +status= implemented description= indicate that the mount point needs some configuration for plugins in order to work. @@ -753,18 +757,6 @@ description = a number of warnings, see src/error/specification -# -# Struct validation -# - - -[struct] -type = vector -status = proposed -description = checks if the subkeys form a valid struct with the given - names. - The validator makes sure that there are no keys for the struct missing. -example = device mpoint type options [dumpfreq] [passno] # @@ -962,12 +954,6 @@ type= string description= A ternary conditional style operator to define relations between keys -[condition/validsuffix] -status= proposal -usedby/plugin= conditionals -type= string -description= A unit of measure style prefix - [check/condition/any/#] status= implemented usedby/plugin= conditionals @@ -986,6 +972,12 @@ usedby/plugin= conditionals type= string description= An array of multiple condition statements +[condition/validsuffix] +status= implemented +usedby/plugin= conditionals +type= string +description= A unit of measure style prefix + [assign/condition] status= implemented usedby/plugin= conditionals @@ -1051,7 +1043,7 @@ description= Trigger an error with given error number from src/error/specificati [trigger/error/nofail] usedby/plugin= error type= long -status= proposal +status= implemented description= Add the error but do not fail (to test robustness of framework). [check/macaddr] @@ -1069,10 +1061,6 @@ status= idea description= Flag keys that will be removed in further versions note= thanks to Config::Model for that idea -[internal//*] -status= implemented -description= Internal metadata to be ignored by other plugins. - [source] status= idea description= states where a key comes from if it is not from an ordinary diff --git a/doc/decisions/README.md b/doc/decisions/README.md index f172fc49f6c..fa5582dbb29 100644 --- a/doc/decisions/README.md +++ b/doc/decisions/README.md @@ -37,26 +37,34 @@ section here. - [High Level API](high_level_api.md) - [Error codes](error_codes.md) - [Error code implementation](error_code_implementation.md) +- [Semantics for Name](semantics_name.md) +- [Base Name](base_name.md) +- [Lookup every key](lookup_every_key.md) +- [Holes and Non-leaf values](holes.md) +- [Multiple File Backends](multiple_file_backends.md) +- [Boolean](boolean.md) + +## In Progress + +- [Global Plugins](global_plugins.md) (@mpranj) +- [Ensure](ensure.md) (@kodebach) +- [Capabilities](capabilities.md) (@markus2330) +- [Error Semantics](error_semantics.md) (API) ## Decided - [Array for Warnings](warning_array.md) +- [Array](array.md) ## In Discussion -- [Semantics for Name](semantics_name.md) -- [Base Name](base_name.md) +- [Escaped Name](escaped_name.md) merge with: - [Store the escaped and/or unescaped key name](store_name.md) -- [Sources for Metadata](metadata_sources.md) -- [Lookup every key](lookup_every_key.md) -- [Holes and Non-leaf values](holes.md) -- [Arbitrary Meta-Data](arbitrary_metadata.md) -- [Multiple File Backends](multiple_file_backends.md) -- [Capabilities](capabilities.md) -- [Array](array.md) -- [Boolean](boolean.md) -- [Global Plugins](global_plugins.md) -- [Vendor Spec](vendor_spec.md) +- [Spec Expressiveness](spec_expressiveness.md) +- [Metadata in Spec Namespace](spec_metadata.md) + +## Delayed + - [Plugin Variants](plugin_variants.md) - [Global Validation](global_validation.md) @@ -66,3 +74,4 @@ section here. - [Null Pointer Checks](null_pointer_checks.md) - [Elektra Web Publish Subscribe](elektra_web_pubsub.md) - [Internal Cache](internal_cache.md) +- [Vendor Spec](vendor_spec.md) diff --git a/doc/decisions/arbitrary_metadata.md b/doc/decisions/arbitrary_metadata.md deleted file mode 100644 index d3ec0d0b2c9..00000000000 --- a/doc/decisions/arbitrary_metadata.md +++ /dev/null @@ -1,39 +0,0 @@ -# Arbitrary Metadata - -## Problem - -To make storage-plugins suitable for `spec` they need to be able to store -all the metadata as specified in [METADATA.ini](/doc/METADATA.ini). -Most file formats do not have support for that. - -## Constraints - -## Assumptions - -## Considered Alternatives - -- store metadata in the comments like the `ini` plugin: - this exposes internal metadata into the comments and - can drastically affect the readability of a storage file. - Comments should never be touched by a parser. - -## Decision - -Use different storage plugins, or plugins with different configurations, -for the `spec` namespace: - -- `ni` -- TOML with `meta` configuration - -## Rationale - -- We do not need a storage plugin suitable for everything. -- The problems that internal metadata ends up in configuration files disappears. - -## Implications - -We need to have different default plugins in `spec` than in the other namespaces. - -## Related Decisions - -## Notes diff --git a/doc/decisions/array.md b/doc/decisions/array.md index 0d26fba0909..2ad925c5160 100644 --- a/doc/decisions/array.md +++ b/doc/decisions/array.md @@ -24,6 +24,10 @@ an array or not. ## Decision Store length in metadata `array` of key, or keep metadata `array` empty if empty array. +Only children that have `#` syntax are allowed in a valid array. +The index start with `#0`. +Both `keyAddName("#12")` or `keyAddBaseName("#_12")` is allowed to add the 13th index. + For example (`ni syntax`, sections used for metadata): ``` @@ -40,8 +44,8 @@ myarray/#5 = value5 It is not allowed to have anything else than `#5` in the metadata `array`, e.g. even `#4` would be a malformed array. -The metadata `array` preferable should be in `spec` (specified configuration). -Then the `spec` plugin will add the `array` marker with the correct length. +With the metadata `array` in `spec:/` the `spec` plugin will add the +`array` marker with the correct length. This needs to be happen early, so that plugins can rely on having correct arrays. @@ -76,12 +80,12 @@ user:/myarray/#0 system:/myarray # <- not found in cascading lookup, as user:/myarray exists ``` -Guarantees we want from the spec plugin: +The `spec` plugin should check if it is a valid array, i.e.: -- that the parent key always contain `array`. -- that the correct length is in `array` -- that the array only contains `#` children -- that the children are numbered from 0 to n, without holes +- that the parent key always contains the metadata `array`, +- that the correct length is in `array`, +- that the array only contains `#` children, and +- that the children are numbered from `#0` to `#n`, without holes. ## Rationale @@ -98,11 +102,17 @@ Guarantees we want from the spec plugin: which is a possibility also in all the alternatives of this decision. - A `user:/` or `dir:/` key can change the semantics of a `system:/` array, if not avoided by `spec`. +- user-facing documentation should contain a note like: + "Mixing array and non-array keys in arrays is not supported. + In many cases the trivial solution is to move the array part into a separate child-key." ## Related Decisions - [Global Plugins](global_plugins.md) - [Global Validation](global_validation.md) +- [Base Names](base_name.md) +- [Metadata in Spec Namespace](spec_metadata.md) +- [Spec Expressiveness](spec_expressiveness.md) ## Notes diff --git a/doc/decisions/boolean.md b/doc/decisions/boolean.md index e826eef6b9b..4c96c24431b 100644 --- a/doc/decisions/boolean.md +++ b/doc/decisions/boolean.md @@ -2,62 +2,53 @@ ## Problem -Inconsistent use of bool in various parts of Elektra. +Inconsistent use of booleans in various parts of Elektra. ## Constraints -## Assumptions - - needs to be string -- convenience plugins can convert anything to 0 or 1 -- type checker plugins can reject everything not 0 or 1 + +## Assumptions ## Considered Alternatives -- strictly only allow 0 and 1 (would move validation across the code) - only check presence or absence (no cascading override of already present key possible) -- use as in CMake (would move convenience across the code) +- use booleans as in CMake, which allows on/off, true/false, ... (would need convenience across the code) +- do not accept a specification with `type = boolean` without a default ## Decision -Use, depending on what your default should be: +Only the strings `0` and `1` are allowed in the `KeySet` for `type = boolean`, for both values and defaults. +Everything else should lead to errors in checkers (in `kdbSet`). -- 0 is false, everything else is true (default is true) -- 1 is true, everything else is false (default is false) +A spec with `type = boolean` without a specified default should be interpreted as `default = 0`. -Example: +Example for an implementation in C in an application: ```c -if ( strcmp(keyString(k), "0")) {/*true*/} else {/*false*/} -if (!strcmp(keyString(k), "1")) {/*true*/} else {/*false*/} +if (k != NULL && strcmp(keyString(k), "1") == 0) {/*true*/} else {/*false*/} ``` -In the documentation it should mention that a bool is used -and which is the default. +Storage plugins are allowed any representation as suitable, e.g., a JSON plugin might render `1` as `true`. The type checker plugin should allow -- non-presence (default) +- non-presence - the string "0" - the string "1" -The convenience plugin should transform (it might be combined with a plugin that transforms everything lower-case): - -- "false", "off", "no" to "0" -- "true", "on", "yes" to "1" - ## Rationale - most easy to implement -- allows presence to be true +- allows non-presence to be false - plugins allow us to convert to any other behavior ## Implications -- change code with different behavior +- Storage plugins are only allowed to emit `0` or `1` as key values +- Applications either get `0` or `1`, or (without a key) + can safely assume that false is meant ## Related Decisions ## Notes - -See [here](https://github.com/ElektraInitiative/libelektra/issues/308) diff --git a/doc/decisions/ensure.md b/doc/decisions/ensure.md new file mode 100644 index 00000000000..eaf9da0ed5f --- /dev/null +++ b/doc/decisions/ensure.md @@ -0,0 +1,86 @@ +# Ensure + +## Problem + +Applications want to ensure that some functionality (=global plugin) +is present in Elektra. + +## Constraints + +## Assumptions + +## Considered Alternatives + +- Keep `kdbEnsure` (Rejected because it is too flexible and can be called many times. Furthermore, + `kdbOpen` would build up configurations that get removed afterwards.) + - reduce for only global plugins, as the partial other functionality is confusing + and not needed + - find solution that list plugin is not needed + - only as implementation detail below libraries (e.g. like done for notification) +- Specific APIs per plugin, Rejected because: + - difficult for application developers + - every plugin would need to design new APIs +- Have a new API: `KDB * kdbOpen (Key * parent);` + `int kdbConfigure (KDB * handle, KeySet * contract, Key * parentKey);` + `KDB * kdbOpenDefault (Key * parent);` + The new kdbOpen only does the absolute minimum work, in particular it doesn't set up any global plugins. + If you use kdbOpen you must call kdbConfigure otherwise kdbGet will fail. kdbConfigure configures global + plugins (basically just a renamed kdbEnsure). Lastly, kdbOpenDefault does more or less what the old kdbOpen + does. It sets up the default case and you can call kdbGet immediately. But you cannot call kdbConfigure after + kdbOpenDefault. + Rejected because of API bloat and introduction of further state in `kdb`. + +## Decision + +Integrate `kdbEnsure` in `kdbOpen(Key *errorKey, KeySet *contract)` but only allow global plugins. + +## Rationale + +- can immediately build up correct plugin positioning +- does not allow to start applications if the contract cannot be fulfilled +- simplest and minimalistic solution + +## Implications + +`elektraNotificationOpen` will only return a contract KeySet: + +```c +KeySet * contract = ksNew (0, KS_END); +elektraNotificationContract (contract, iobinding); +``` + +The same for gopts: + +```c +elektraGOptsContract (contract, argc, argv, environ); +``` + +Finally, we create `KDB` with the contracts we got before: + +```c +KDB * kdb = kdbOpen (key, contract); +``` + +Opening `KDB` will fail if any of the contracts cannot be ensured. + +As the `contract` gets copied, at any point after `kdbOpen` the +contract can be safely deleted: + +``` +ksDel (contract); +``` + +The cleanup of the global plugins happens within: + +```c +kdbClose (kdb, errorKey); +``` + +It is safe to use the contract `KeySet` also for `kdbGet` and `kdbSet` +invocations. + +## Related Decisions + +- [Global Plugins](global_plugins.md) + +## Notes diff --git a/doc/decisions/error_code_implementation.md b/doc/decisions/error_code_implementation.md index 6012adbca1c..c53da866183 100644 --- a/doc/decisions/error_code_implementation.md +++ b/doc/decisions/error_code_implementation.md @@ -2,7 +2,8 @@ ## Problem -In the previous error concept it was very useful to generate macros as we often added new errors. The code generation itself, however, is quite complicated (C++ code that prints the code; which is also not ideal for cross compilation, see also https://github.com/ElektraInitiative/libelektra/issues/2814). +In the previous error concept it was very useful to generate macros as we often added new errors. +The code generation itself, however, was not ideal for cross compilation. ## Constraints @@ -15,9 +16,9 @@ In the previous error concept it was very useful to generate macros as we often - Migrate to a more modern and easier way to generate code with our mustache system, and let this generate the (mapping) code for all compiled languages (C, C++, Java, Rust, Go). All we get out of this is the removal of `std::cout << ...` code from C++ but not much more. -- Migrate to CMake code that generates such macros/classes (see also https://github.com/ElektraInitiative/libelektra/issues/2814) +- Migrate to CMake code that generates such macros/classes. Mustache templates have to be supplied with the input data somehow. Either we have to use a custom executable that is compiled at build time. - In that case we would just get rid of the std::cout << ... in the C++ code, but not much else would change. + In that case we would just get rid of the `std::cout << ...` in the C++ code, but not much else would change. The other option is to use the default mustache executable, which is a Ruby script and therefore requires Ruby to be installed. Also kdb gen cannot be reused, since that would require compiling kdb first, which needs kdberrors.h. @@ -44,5 +45,5 @@ When adding a new error code, language bindings have to be adapted accordingly s ## Notes -- https://github.com/ElektraInitiative/libelektra/issues/2871 -- https://github.com/ElektraInitiative/libelektra/issues/2814 +- See also [Issue #2814](https://issues.libelektra.org/2814) +- See also [Issue #2871](https://issues.libelektra.org/2871) diff --git a/doc/decisions/error_semantics.md b/doc/decisions/error_semantics.md new file mode 100644 index 00000000000..cbc990484b0 --- /dev/null +++ b/doc/decisions/error_semantics.md @@ -0,0 +1,57 @@ +# Error Semantics + +## Problem + +While we have a classification of errors and warnings, it remains +unclear when plugins actually should emit errors and warnings. + +## Constraints + +- Should not be contradicting to specified behavior in [storage plugin tutorial](/doc/tutorials/storage-plugins.md). + +## Assumptions + +- Users want a uniform behavior within Elektra, so plugins must behave uniformly. + +## Considered Alternatives + +- freedom to plugin writers +- strict rules and conformance tests for plugins + +## Decision + +Provide guidelines in the form as tutorials, covering: + +- prefer errors to warnings +- that any not understood metadata (e.g. types), should lead to an error +- that wrong specifications, like `kdb meta-set /tests/ipaddr/ipv4 check/ipaddr ipv8` should be rejected +- if the value does not confirm **exactly** to the specified type, an error should be emitted + (e.g. only `0` or `1` as boolean) +- anything else that is beyond the capabilities of a plugin (not implemented), + should lead to an error + +Violations against these guidelines can be reported as bug and then either: + +- the bug gets fixed +- the plugin get a worse `infos/status` but still get shipped with 1.0 +- the plugin gets removed + +## Rationale + +It is easier for developers if there are clear expectations on how a plugin +should behave. And it is much easier for overall Elektra if there is more +consistency. + +## Implications + +- more checks&errors in storage plugins are needed + +## Related Decisions + +- [Metadata in Spec Namespace](spec_metadata.md) +- [Capabilities](capabilities.md) +- [Boolean](boolean.md) + +## Notes + +- [Issue #1511](https://issues.libelektra.org/1511) diff --git a/doc/decisions/escaped_name.md b/doc/decisions/escaped_name.md new file mode 100644 index 00000000000..12d7327947d --- /dev/null +++ b/doc/decisions/escaped_name.md @@ -0,0 +1,54 @@ +# Escaped Name + +## Problem + +Currently we store both the escaped and unescaped name in a Key and in +a way that there cannot be an optimization not to store it (there are +functions handling out the pointer). + +## Constraints + +- allow implementations of Elektra to not store two names + +## Assumptions + +- the memory consumption of storing the name twice is considerable + +## Considered Alternatives + +- store it twice +- store it once but in one memory block + +## Decision + +Remove the escaped name from `struct _Key` and use it only when necessary. + +Clarify and reduce [terminology](/doc/help/elektra-glossary.md). + +API Changes: + +- `keyName` returns the unescaped name + (temporary some other name for PR: `keyUnescapedName(Size)`) +- remove `keyUnescapedName`, `keyGetUnescapedNameSize`. +- reverse terminology: with "key name" we will refer to the unescaped (base) name, + the escaped name will be explicitly called "escaped key name". +- escaped name will be only present in + - `keyNew` (+ arguments for adding key names) [unclear: maybe not needed] + - `elektraEscapeName` (operating on chars) + - rename `keyAddName`, e.g. to `keyAddEscapedName` +- `keyDup(.., int)` with options to filter which parts are copied + (to allow copy of keys where only the key name is copied) + +## Rationale + +## Implications + +- needs fix of OPMPHM +- Later modifications in keyNew to also accept key base names might be useful: + +- keyNew(KEY_VALUE, "...", KEY_NAME, "", "...", KEY_END) +- keyNew (KEY_NAME, KEY_NS_USER, "abc", "def", KEY_NAME_END, KEY_END); + +## Related Decisions + +## Notes diff --git a/doc/decisions/global_plugins.md b/doc/decisions/global_plugins.md index e4dcd38972d..e4d7186ae99 100644 --- a/doc/decisions/global_plugins.md +++ b/doc/decisions/global_plugins.md @@ -42,6 +42,8 @@ We need to cleanup and simplify the placement. Have hooks and API specific to the list of global plugins in assumptions. These hooks are not shared, so no `list` plugin is needed. +Installed plugins will be used. + ## Rationale - allows adding more types of plugins later, also post-1.0 @@ -50,6 +52,8 @@ These hooks are not shared, so no `list` plugin is needed. ## Implications +- remove `global-mount` command +- command for mmap/notification/... enable disable (like current `kdb cache` tool) - remove `list` plugin - remove plugins that stop working or disallow global positioning for them - call `spec` as needed several times diff --git a/doc/decisions/global_validation.md b/doc/decisions/global_validation.md index 698fc580d7a..cbc1abe05b4 100644 --- a/doc/decisions/global_validation.md +++ b/doc/decisions/global_validation.md @@ -24,10 +24,14 @@ with the respective `kdbGet`. ## Decision -- always load everything (with mmap) +Not supported, admins/maintainers need to stay with their spec within what applications request by `kdbGet`. ## Rationale +- it is too expensive to always load all keys (@mpranj: is this true?) +- problems in implementing to always get everything +- it makes the parameter to `kdbGet` basically useless + ## Implications ## Related Decisions diff --git a/doc/decisions/holes.md b/doc/decisions/holes.md index 4c18232054a..bd77a072167 100644 --- a/doc/decisions/holes.md +++ b/doc/decisions/holes.md @@ -37,7 +37,7 @@ Support holes and values for non-leaves in a KeySet if the underlying format all If the underlying format does not support it and there is also not an obvious way how to circumvent it -- e.g., JSON which does not have comments -- holes and -values in non-leaves are not supported. +values in non-leaves can be supported with key names starting with ®elektra. ## Rationale diff --git a/doc/decisions/metadata_sources.md b/doc/decisions/metadata_sources.md deleted file mode 100644 index fe15c8134e5..00000000000 --- a/doc/decisions/metadata_sources.md +++ /dev/null @@ -1,23 +0,0 @@ -# Metadata Sources - -## Problem - -If metadata is merged from different sources, metadata from spec might end up somewhere else. - -## Constraints - -## Assumptions - -## Considered Alternatives - -## Decision - -Do not store metadata in any namespace but spec. - -## Rationale - -## Implications - -## Related Decisions - -## Notes diff --git a/doc/decisions/semantics_name.md b/doc/decisions/semantics_name.md index 115ccd9da27..9f44fa2a9aa 100644 --- a/doc/decisions/semantics_name.md +++ b/doc/decisions/semantics_name.md @@ -19,15 +19,33 @@ The alternative would be to have semantics in key names, with following advantag Do not encode any semantics into the key names. All semantic must be in metadata. +Nevertheless, there are guidelines (without any checks in `keySetBaseName`): + +- `#` is used to indicate that array numbers follow. +- `®` is used to indicate that some information was encoded in the key name. + This is usually only needed internally in storage plugins. +- The UTF-8 sequence `®elektra` (i.e. the 9-byte sequence `C2 AE 65 6C 65 6B 74 72 61`) is reserved, + see key name docu. + There are, however, rules and conventions which syntax to use for specific semantics. The `spec` plugin guards these rules. ## Rationale +- for consistency, whenever possible, metadata should be preferred +- no escaping of key base names necessary +- it is very unlikely that `®elektra` collides with a real key base name + a user wanted to have +- `®elektra` makes very clear that there is a special reserved meaning +- `®elektra` UTF-8 encoding decodes to "some character" + ® in many 8-bit encodings + (including ISO 8859-1 aka Latin1 and Windows (Codepage) 1252, + in the encoding `C`, however, you get `''$'\302\256''elektra'`) + ## Implications ## Related Decisions - [Arrays](array.md) +- [Base Names](base_name.md) ## Notes diff --git a/doc/decisions/spec_expressiveness.md b/doc/decisions/spec_expressiveness.md new file mode 100644 index 00000000000..b9307a66d66 --- /dev/null +++ b/doc/decisions/spec_expressiveness.md @@ -0,0 +1,30 @@ +# Spec's Expressiveness + +## Problem + +Currently, you can easily come into wrong assumptions +that something would work in the specification. + +We need to find minimal requirements to implement a sane spec plugin. + +## Constraints + +## Assumptions + +## Considered Alternatives + +## Decision + +- no defaults for `sw/_/key` specifications + (default will not work for `ksLookup(/sw/sthg/key)`) +- plugins are not allowed to create keys (may change in future; depends on plugin positions) + +The spec plugin should yield errors when it detects such situations. + +## Rationale + +## Implications + +## Related Decisions + +## Notes diff --git a/doc/decisions/spec_metadata.md b/doc/decisions/spec_metadata.md new file mode 100644 index 00000000000..129122387d3 --- /dev/null +++ b/doc/decisions/spec_metadata.md @@ -0,0 +1,94 @@ +# Metadata in Spec Namespace + +## Problem + +To make storage-plugins suitable for `spec` they need to be able to store +all the metadata as specified in [METADATA.ini](/doc/METADATA.ini). +Most file formats do not have support for that. + +If metadata is merged from different namespaces, e.g., `spec:` and `user:`, +metadata from one namespace might end up in keys of other namespaces, e.g., +metadata from `spec:` might end up in `user:`. + +## Constraints + +- We do not touch what is already described in the + [storage plugin tutorial](/doc/tutorials/storage-plugins.md). + +## Assumptions + +- Metadata can always safely merged from `spec:/` to other + namespace. + +## Considered Alternatives + +- Store metadata in the comments like the `ini` plugin: + this exposes internal metadata into the comments and + can drastically affect the readability of a storage file. + Comments should never be touched by a parser. +- Designate metadata to be only for `spec:/` or to only + for restoring configuration file formats. + Rename metadata `` in `spec:/` to `check/` + or `make/array`. + This way no merging of metadata would be needed and + by the name alone it would be clear to which namespace + it belongs. +- Do not support `array` or `type` if the underlying + configuration file format does not support it. + `spec-mount` could make sure that the storage plugin + supports everything the underlying format needs. + +## Decision + +Do not store metadata unrelated to the configuration file structure in any namespace except in `spec:/`. + +- Trying to store any other metadata in any other namespace leads to an error. + E.g. `kdb set-meta user:/data metadata_not_suitable_for_storage_plugins something` would fail + (validated by `spec` plugin). +- Metadata that is designed to be stored by storage plugins to preserve configuration file structure. + E.g. `comment` or `order`, might be stored in any namespace. + +Sometimes, the same metadata can be used in several namespaces but with different meanings +and ways of serialization, e.g. `type` and `array`: + +- In `spec:/` the metadata `array=` (empty value) means "this is an array". + If you give it a value e.g. `array=#4` it means "this is an array with default size X" (e.g. `#4` = size 5). +- In any other namespace `array=` means "this is an empty array" and e.g. `array=#4` means "this is an array with max index #4". + `array=#4` is not stored literally but inferred. +- Either the storage plugin does not support arrays, then the metadata will be discarded + on `kdbSet` but `spec` will keep on adding it for every `kdbGet`. +- Or, if the storage plugin supports arrays, the data will be serialized as array + (even if the metadata comes from `spec`) and as such available in the next `kdbGet` + from the storage plugin to be validated by `spec`. + +Use different storage plugins, or plugins with different configurations, +for the `spec:/` namespace: + +- `ni` +- TOML with `meta` configuration + +The `kdb mount` tool will add the `meta` plugin configuration when mounting a storage plugin to `spec:/`. + +## Rationale + +- We do not need a storage plugin suitable for everything. +- The problems that internal metadata ends up in configuration files disappears. +- The short names `type` and `array` can be used in specs. +- Also simple storage plugins (like properties) can still be used with realistic + specifications (that include array and/or type). + +## Implications + +- We need to have different (default) plugins in `spec:/` than in the other namespaces. +- It can be confusing about which metadata we are speaking, e.g., `array` in + `spec:/` has a quite different meaning to `array` in other namespaces. +- The spec:/ meaning of array= must obviously be stored. The other meaning should never + be stored explicitly and instead should be inferred from the stored data. Either by + the storage plugin (e.g. JSON array) or by the spec plugin. + +## Related Decisions + +- [Spec Expressiveness](spec_expressiveness.md) +- [Arrays](array.md) + +## Notes diff --git a/doc/decisions/vendor_spec.md b/doc/decisions/vendor_spec.md index 793df8eba1f..010b44d7627 100644 --- a/doc/decisions/vendor_spec.md +++ b/doc/decisions/vendor_spec.md @@ -22,7 +22,9 @@ and being administer friendly. ## Decision -Provide means that a single specification can satisfy every distribution and administrator. +As found out during implementation of [specload](/src/plugins/specload), only a very limited subset can be modified safely, e.g.: + +- add/edit/remove `description`, `opt/help` and `comment` ## Rationale diff --git a/doc/news/_preparation_next_release.md b/doc/news/_preparation_next_release.md index 35c0bed65c8..f8cc4c9519c 100644 --- a/doc/news/_preparation_next_release.md +++ b/doc/news/_preparation_next_release.md @@ -147,7 +147,7 @@ you up to date with the multi-language support provided by Elektra. ## Documentation -- <> +- Finalize 1.0 decisions. _(Markus Raab)_ - <> - <> diff --git a/doc/tutorials/README.md b/doc/tutorials/README.md index b93e8d4e71b..fcb24da7739 100644 --- a/doc/tutorials/README.md +++ b/doc/tutorials/README.md @@ -19,8 +19,8 @@ application, that means, you want your application to participate in the global key database Elektra provides. -- [Integration of your Application](application-integration.md) -- [Hello, Elektra](hello-elektra.md) +- [Hello, Elektra in C](hello-elektra.md) +- [Integration of your C Application](application-integration.md) - [Plugins Introduction](plugins.md) - [Storage Plugins](storage-plugins.md) - [Compilation Variants of plugins](compilation-variants.md) (advanced topic) diff --git a/scripts/cmake/ElektraCache.cmake b/scripts/cmake/ElektraCache.cmake index b9329ec5e56..2d2a47f6f7d 100644 --- a/scripts/cmake/ElektraCache.cmake +++ b/scripts/cmake/ElektraCache.cmake @@ -423,6 +423,8 @@ mark_as_advanced ( pkgcfg_lib__LIBSYSTEMD_PC_syst pkgcfg_lib__OPENSSL_crypto pkgcfg_lib__OPENSSL_ssl + pkgcfg_lib_PC_yaml-cpp_yaml-cpp + pkgcfg_lib__LIBSYSTEMD_PC_systemd SWIG_DIR SWIG_VERSION gtest_build_samples diff --git a/scripts/sed b/scripts/sed index 4861bf5f91a..65ab51d540a 100644 --- a/scripts/sed +++ b/scripts/sed @@ -1,3 +1,5 @@ +# use scripts/dev/fix-spelling to apply these corrections + # ================= # = General Terms = # ================= diff --git a/src/libs/invoke/invoke.c b/src/libs/invoke/invoke.c index ee3015fef96..820d6c64033 100644 --- a/src/libs/invoke/invoke.c +++ b/src/libs/invoke/invoke.c @@ -377,7 +377,7 @@ void elektraInvokeExecuteDeferredCalls (ElektraInvokeHandle * handle, ElektraDef } /** - * Call a deferable function on a plugin handle. + * Call a deferrable function on a plugin handle. * If the function is exported by the plugin it is directly invoked, * if the plugin supports deferring calls, the call is deferred. * If both is possible (function is exported and deferred calls are supported), diff --git a/tests/shell/check_spelling.sh b/tests/shell/check_spelling.sh index c842ac1b0dc..7a4ccd94bfd 100755 --- a/tests/shell/check_spelling.sh +++ b/tests/shell/check_spelling.sh @@ -15,6 +15,7 @@ scripts/dev/fix-spelling git diff --exit-code succeed_if 'Please commit the spelling fixes before pushing. +Use scripts/dev/fix-spelling to make the changes, or apply the patch shown above. If one of the spelling fixes was incorrect, then please update `/scripts/sed` accordingly.' printf '\n'