From 49d61b2e4bf338042364c85d3c2ead0b33963e65 Mon Sep 17 00:00:00 2001 From: piegames Date: Sat, 13 Jul 2024 05:24:41 +0200 Subject: libexpr: Introduce Deprecated features They are like experimental features, but opt-in instead of opt-out. They will allow us to gracefully remove language features. See #437 Change-Id: I9ca04cc48e6926750c4d622c2b229b25cc142c42 --- doc/manual/generate-features-shortlist.nix | 14 ++++++++ doc/manual/generate-features.nix | 18 +++++++++++ doc/manual/generate-xp-features-shortlist.nix | 9 ------ doc/manual/generate-xp-features.nix | 13 -------- doc/manual/meson.build | 6 ++-- doc/manual/src/SUMMARY.md | 1 + doc/manual/src/command-ref/meson.build | 25 +++++++++++++-- doc/manual/src/contributing/deprecated-features.md | 37 ++++++++++++++++++++++ doc/manual/src/contributing/meson.build | 17 ++++++++-- 9 files changed, 112 insertions(+), 28 deletions(-) create mode 100644 doc/manual/generate-features-shortlist.nix create mode 100644 doc/manual/generate-features.nix delete mode 100644 doc/manual/generate-xp-features-shortlist.nix delete mode 100644 doc/manual/generate-xp-features.nix create mode 100644 doc/manual/src/contributing/deprecated-features.md (limited to 'doc') diff --git a/doc/manual/generate-features-shortlist.nix b/doc/manual/generate-features-shortlist.nix new file mode 100644 index 000000000..055698d64 --- /dev/null +++ b/doc/manual/generate-features-shortlist.nix @@ -0,0 +1,14 @@ +# Usually "experimental" or "deprecated" +kind: +# "xp" or "dp" +kindShort: + +with builtins; +with import ./utils.nix; + +let + showExperimentalFeature = name: doc: '' + - [`${name}`](@docroot@/contributing/${kind}-features.md#${kindShort}-feature-${name}) + ''; +in +xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/generate-features.nix b/doc/manual/generate-features.nix new file mode 100644 index 000000000..4a12ccdce --- /dev/null +++ b/doc/manual/generate-features.nix @@ -0,0 +1,18 @@ +# Usually "experimental" or "deprecated" +_kind: +# "xp" or "dp" +kindShort: + +with builtins; +with import ./utils.nix; + +let + showFeature = + name: doc: + squash '' + ## [`${name}`]{#${kindShort}-feature-${name}} + + ${doc} + ''; +in +xps: (concatStringsSep "\n" (attrValues (mapAttrs showFeature xps))) diff --git a/doc/manual/generate-xp-features-shortlist.nix b/doc/manual/generate-xp-features-shortlist.nix deleted file mode 100644 index ea8bf8d49..000000000 --- a/doc/manual/generate-xp-features-shortlist.nix +++ /dev/null @@ -1,9 +0,0 @@ -with builtins; -with import ./utils.nix; - -let - showExperimentalFeature = name: doc: '' - - [`${name}`](@docroot@/contributing/experimental-features.md#xp-feature-${name}) - ''; -in -xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/generate-xp-features.nix b/doc/manual/generate-xp-features.nix deleted file mode 100644 index c56ddeea1..000000000 --- a/doc/manual/generate-xp-features.nix +++ /dev/null @@ -1,13 +0,0 @@ -with builtins; -with import ./utils.nix; - -let - showExperimentalFeature = - name: doc: - squash '' - ## [`${name}`]{#xp-feature-${name}} - - ${doc} - ''; -in -xps: (concatStringsSep "\n" (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/meson.build b/doc/manual/meson.build index 673c86149..1bdbba77e 100644 --- a/doc/manual/meson.build +++ b/doc/manual/meson.build @@ -72,9 +72,9 @@ generate_manual_deps = files( # Generates builtins.md and builtin-constants.md. subdir('src/language') -# Generates new-cli pages, experimental-features-shortlist.md, and conf-file.md. +# Generates new-cli pages, {experimental,deprecated}-features-shortlist.md, and conf-file.md. subdir('src/command-ref') -# Generates experimental-feature-descriptions.md. +# Generates {experimental,deprecated}-feature-descriptions.md. subdir('src/contributing') # Generates rl-next-generated.md. subdir('src/release-notes') @@ -106,6 +106,8 @@ manual = custom_target( nix3_cli_files, experimental_features_shortlist_md, experimental_feature_descriptions_md, + deprecated_features_shortlist_md, + deprecated_feature_descriptions_md, conf_file_md, builtins_md, builtin_constants_md, diff --git a/doc/manual/src/SUMMARY.md b/doc/manual/src/SUMMARY.md index 4fac7cbca..03dc7e198 100644 --- a/doc/manual/src/SUMMARY.md +++ b/doc/manual/src/SUMMARY.md @@ -192,6 +192,7 @@ - [Hacking](contributing/hacking.md) - [Testing](contributing/testing.md) - [Experimental Features](contributing/experimental-features.md) + - [Deprecated Features](contributing/deprecated-features.md) - [CLI guideline](contributing/cli-guideline.md) - [C++ style guide](contributing/cxx.md) - [Release Notes](release-notes/release-notes.md) diff --git a/doc/manual/src/command-ref/meson.build b/doc/manual/src/command-ref/meson.build index 03d5f0a9c..ef6f9d2e0 100644 --- a/doc/manual/src/command-ref/meson.build +++ b/doc/manual/src/command-ref/meson.build @@ -7,10 +7,10 @@ xp_features_json = custom_target( experimental_features_shortlist_md = custom_target( command : nix_eval_for_docs + [ '--expr', - 'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))', + 'import @INPUT0@ "experimental" "xp" (builtins.fromJSON (builtins.readFile @INPUT1@))', ], input : [ - '../../generate-xp-features-shortlist.nix', + '../../generate-features-shortlist.nix', xp_features_json, ], capture : true, @@ -18,6 +18,26 @@ experimental_features_shortlist_md = custom_target( env : nix_env_for_docs, ) +dp_features_json = custom_target( + command : [nix, '__dump-dp-features'], + capture : true, + output : 'dp-features.json', +) + +deprecated_features_shortlist_md = custom_target( + command : nix_eval_for_docs + [ + '--expr', + 'import @INPUT0@ "deprecated" "dp" (builtins.fromJSON (builtins.readFile @INPUT1@))', + ], + input : [ + '../../generate-features-shortlist.nix', + dp_features_json, + ], + capture : true, + output : 'deprecated-features-shortlist.md', + env : nix_env_for_docs, +) + # Intermediate step for manpage generation. # This splorks the output of generate-manpage.nix as JSON, # which gets written as a directory tree below. @@ -60,6 +80,7 @@ conf_file_md = custom_target( '../../utils.nix', conf_file_json, experimental_features_shortlist_md, + deprecated_features_shortlist_md, ], output : 'conf-file.md', env : nix_env_for_docs, diff --git a/doc/manual/src/contributing/deprecated-features.md b/doc/manual/src/contributing/deprecated-features.md new file mode 100644 index 000000000..7536944f7 --- /dev/null +++ b/doc/manual/src/contributing/deprecated-features.md @@ -0,0 +1,37 @@ +This section describes the notion of *deprecated features*, and how it fits into the big picture of the development of Lix. + +# What are deprecated features? + +Deprecated features are disabled by default, with the intent to eventually remove them. +Users must explicitly enable them to keep using them, by toggling the associated [deprecated feature flags](@docroot@/command-ref/conf-file.md#conf-deprecated-features). +This allows backwards compatibility and a graceful transition away from undesired features. + +# Which features can be deprecated? + +Undesired features should be soft-deprecated by yielding a warning when used for a significant amount of time before the can be deprecated. +Legacy obsolete feature with little to no usage may go through this process faster. +Deprecated features should have a migration path to a preferred alternative. + +# Lifecycle of a deprecated feature + +This description is not normative, but a feature removal may roughly happen like this: + +1. Add a warning when the feature is being used. +2. Disable the feature by default, putting it behind a deprecated feature flag. + - If disabling the feature started out as an opt-in experimental feature, turn that experimental flag into a no-op or remove it entirely. + For example, `--extra-experimental-features=no-url-literals` becomes `--extra-deprecated-features=url-literals`. +3. Decide on a time frame for how long that feature will still be supported for backwards compatibility, and clearly communicate that in the error messages. + - Sometimes, automatic migration to alternatives is possible, and such should be provided if possible + - At least one NixOS release cycle should be the minimum +4. Finally remove the feature entirely, only keeping the error message for those still using it. + +# Relation to language versioning + +Obviously, removing anything breaks backwards compatibility. +In an ideal world, we'd have SemVer controls over the language and its features, cleanly allowing us to make breaking changes. +See https://wiki.lix.systems/books/lix-contributors/page/language-versioning and [RFC 137](https://github.com/nixos/rfcs/pull/137) for efforts on that. +However, we do not live in such an ideal world, and currently this goal is so far away, that "just disable it with some back-compat for a couple of years" is the most realistic solution, especially for comparatively minor changes. + +# Currently available deprecated features + +{{#include @generated@/contributing/deprecated-feature-descriptions.md}} diff --git a/doc/manual/src/contributing/meson.build b/doc/manual/src/contributing/meson.build index 2929578c8..8c76a6206 100644 --- a/doc/manual/src/contributing/meson.build +++ b/doc/manual/src/contributing/meson.build @@ -4,12 +4,25 @@ experimental_feature_descriptions_md = custom_target( command : nix_eval_for_docs + [ '--expr', - 'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))', + 'import @INPUT0@ "experimental" "xp" (builtins.fromJSON (builtins.readFile @INPUT1@))', ], input : [ - '../../generate-xp-features.nix', + '../../generate-features.nix', xp_features_json, ], capture : true, output : 'experimental-feature-descriptions.md', ) + +deprecated_feature_descriptions_md = custom_target( + command : nix_eval_for_docs + [ + '--expr', + 'import @INPUT0@ "deprecated" "dp" (builtins.fromJSON (builtins.readFile @INPUT1@))', + ], + input : [ + '../../generate-features.nix', + dp_features_json, + ], + capture : true, + output : 'deprecated-feature-descriptions.md', +) -- cgit v1.2.3