···3{ lib }:
4let
5 inherit (lib.strings) toInt;
6- inherit (lib.trivial) compare min;
7 inherit (lib.attrsets) mapAttrs;
8in
9rec {
···180 else if len != 1 then multiple
181 else head found;
182183- /* Find the first element in the list matching the specified
184 predicate or return `default` if no such element exists.
185186- Type: findFirst :: (a -> bool) -> a -> [a] -> a
187188 Example:
189- findFirst (x: x > 3) 7 [ 1 6 4 ]
190- => 6
191- findFirst (x: x > 9) 7 [ 1 6 4 ]
192- => 7
193 */
194- findFirst =
195 # Predicate
196 pred:
197 # Default value to return
···229 if resultIndex < 0 then
230 default
231 else
232- elemAt list resultIndex;
00000000000000000000000000233234 /* Return true if function `pred` returns true for at least one
235 element of `list`.
···636 (if start >= len then 0
637 else if start + count > len then len - start
638 else count);
00000000000000000000000000639640 /* Return the last element of a list.
641
···3{ lib }:
4let
5 inherit (lib.strings) toInt;
6+ inherit (lib.trivial) compare min id;
7 inherit (lib.attrsets) mapAttrs;
8in
9rec {
···180 else if len != 1 then multiple
181 else head found;
182183+ /* Find the first index in the list matching the specified
184 predicate or return `default` if no such element exists.
185186+ Type: findFirstIndex :: (a -> Bool) -> b -> [a] -> (Int | b)
187188 Example:
189+ findFirstIndex (x: x > 3) null [ 0 6 4 ]
190+ => 1
191+ findFirstIndex (x: x > 9) null [ 0 6 4 ]
192+ => null
193 */
194+ findFirstIndex =
195 # Predicate
196 pred:
197 # Default value to return
···229 if resultIndex < 0 then
230 default
231 else
232+ resultIndex;
233+234+ /* Find the first element in the list matching the specified
235+ predicate or return `default` if no such element exists.
236+237+ Type: findFirst :: (a -> bool) -> a -> [a] -> a
238+239+ Example:
240+ findFirst (x: x > 3) 7 [ 1 6 4 ]
241+ => 6
242+ findFirst (x: x > 9) 7 [ 1 6 4 ]
243+ => 7
244+ */
245+ findFirst =
246+ # Predicate
247+ pred:
248+ # Default value to return
249+ default:
250+ # Input list
251+ list:
252+ let
253+ index = findFirstIndex pred null list;
254+ in
255+ if index == null then
256+ default
257+ else
258+ elemAt list index;
259260 /* Return true if function `pred` returns true for at least one
261 element of `list`.
···662 (if start >= len then 0
663 else if start + count > len then len - start
664 else count);
665+666+ /* The common prefix of two lists.
667+668+ Type: commonPrefix :: [a] -> [a] -> [a]
669+670+ Example:
671+ commonPrefix [ 1 2 3 4 5 6 ] [ 1 2 4 8 ]
672+ => [ 1 2 ]
673+ commonPrefix [ 1 2 3 ] [ 1 2 3 4 5 ]
674+ => [ 1 2 3 ]
675+ commonPrefix [ 1 2 3 ] [ 4 5 6 ]
676+ => [ ]
677+ */
678+ commonPrefix =
679+ list1:
680+ list2:
681+ let
682+ # Zip the lists together into a list of booleans whether each element matches
683+ matchings = zipListsWith (fst: snd: fst != snd) list1 list2;
684+ # Find the first index where the elements don't match,
685+ # which will then also be the length of the common prefix.
686+ # If all elements match, we fall back to the length of the zipped list,
687+ # which is the same as the length of the smaller list.
688+ commonPrefixLength = findFirstIndex id (length matchings) matchings;
689+ in
690+ take commonPrefixLength list1;
691692 /* Return the last element of a list.
693
+63-20
lib/tests/misc.nix
···500 expected = { a = [ 2 3 ]; b = [7]; c = [8];};
501 };
502000000000000000000000000000000000503 testSort = {
504 expr = sort builtins.lessThan [ 40 2 30 42 ];
505 expected = [2 30 40 42];
···530 expected = false;
531 };
532533- testFindFirstExample1 = {
534- expr = findFirst (x: x > 3) 7 [ 1 6 4 ];
535- expected = 6;
536 };
537538- testFindFirstExample2 = {
539- expr = findFirst (x: x > 9) 7 [ 1 6 4 ];
540- expected = 7;
541 };
542543- testFindFirstEmpty = {
544- expr = findFirst (abort "when the list is empty, the predicate is not needed") null [];
545 expected = null;
546 };
547548- testFindFirstSingleMatch = {
549- expr = findFirst (x: x == 5) null [ 5 ];
550- expected = 5;
551 };
552553- testFindFirstSingleDefault = {
554- expr = findFirst (x: false) null [ (abort "if the predicate doesn't access the value, it must not be evaluated") ];
555 expected = null;
556 };
557558- testFindFirstNone = {
559- expr = builtins.tryEval (findFirst (x: x == 2) null [ 1 (throw "the last element must be evaluated when there's no match") ]);
560 expected = { success = false; value = false; };
561 };
562563 # Makes sure that the implementation doesn't cause a stack overflow
564- testFindFirstBig = {
565- expr = findFirst (x: x == 1000000) null (range 0 1000000);
566 expected = 1000000;
567 };
568569- testFindFirstLazy = {
570- expr = findFirst (x: x == 1) 7 [ 1 (abort "list elements after the match must not be evaluated") ];
571- expected = 1;
0000000000572 };
573574# ATTRSETS
···500 expected = { a = [ 2 3 ]; b = [7]; c = [8];};
501 };
502503+ testListCommonPrefixExample1 = {
504+ expr = lists.commonPrefix [ 1 2 3 4 5 6 ] [ 1 2 4 8 ];
505+ expected = [ 1 2 ];
506+ };
507+ testListCommonPrefixExample2 = {
508+ expr = lists.commonPrefix [ 1 2 3 ] [ 1 2 3 4 5 ];
509+ expected = [ 1 2 3 ];
510+ };
511+ testListCommonPrefixExample3 = {
512+ expr = lists.commonPrefix [ 1 2 3 ] [ 4 5 6 ];
513+ expected = [ ];
514+ };
515+ testListCommonPrefixEmpty = {
516+ expr = lists.commonPrefix [ ] [ 1 2 3 ];
517+ expected = [ ];
518+ };
519+ testListCommonPrefixSame = {
520+ expr = lists.commonPrefix [ 1 2 3 ] [ 1 2 3 ];
521+ expected = [ 1 2 3 ];
522+ };
523+ testListCommonPrefixLazy = {
524+ expr = lists.commonPrefix [ 1 ] [ 1 (abort "lib.lists.commonPrefix shouldn't evaluate this")];
525+ expected = [ 1 ];
526+ };
527+ # This would stack overflow if `commonPrefix` were implemented using recursion
528+ testListCommonPrefixLong =
529+ let
530+ longList = genList (n: n) 100000;
531+ in {
532+ expr = lists.commonPrefix longList longList;
533+ expected = longList;
534+ };
535+536 testSort = {
537 expr = sort builtins.lessThan [ 40 2 30 42 ];
538 expected = [2 30 40 42];
···563 expected = false;
564 };
565566+ testFindFirstIndexExample1 = {
567+ expr = lists.findFirstIndex (x: x > 3) (abort "index found, so a default must not be evaluated") [ 1 6 4 ];
568+ expected = 1;
569 };
570571+ testFindFirstIndexExample2 = {
572+ expr = lists.findFirstIndex (x: x > 9) "a very specific default" [ 1 6 4 ];
573+ expected = "a very specific default";
574 };
575576+ testFindFirstIndexEmpty = {
577+ expr = lists.findFirstIndex (abort "when the list is empty, the predicate is not needed") null [];
578 expected = null;
579 };
580581+ testFindFirstIndexSingleMatch = {
582+ expr = lists.findFirstIndex (x: x == 5) null [ 5 ];
583+ expected = 0;
584 };
585586+ testFindFirstIndexSingleDefault = {
587+ expr = lists.findFirstIndex (x: false) null [ (abort "if the predicate doesn't access the value, it must not be evaluated") ];
588 expected = null;
589 };
590591+ testFindFirstIndexNone = {
592+ expr = builtins.tryEval (lists.findFirstIndex (x: x == 2) null [ 1 (throw "the last element must be evaluated when there's no match") ]);
593 expected = { success = false; value = false; };
594 };
595596 # Makes sure that the implementation doesn't cause a stack overflow
597+ testFindFirstIndexBig = {
598+ expr = lists.findFirstIndex (x: x == 1000000) null (range 0 1000000);
599 expected = 1000000;
600 };
601602+ testFindFirstIndexLazy = {
603+ expr = lists.findFirstIndex (x: x == 1) null [ 1 (abort "list elements after the match must not be evaluated") ];
604+ expected = 0;
605+ };
606+607+ testFindFirstExample1 = {
608+ expr = lists.findFirst (x: x > 3) 7 [ 1 6 4 ];
609+ expected = 6;
610+ };
611+612+ testFindFirstExample2 = {
613+ expr = lists.findFirst (x: x > 9) 7 [ 1 6 4 ];
614+ expected = 7;
615 };
616617# ATTRSETS
+3
nixos/doc/manual/release-notes/rl-2311.section.md
···3435- [ebusd](https://ebusd.eu), a daemon for handling communication with eBUS devices connected to a 2-wire bus system (“energy bus” used by numerous heating systems). Available as [services.ebusd](#opt-services.ebusd.enable).
3603738## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
39···140- `services.prometheus.exporters` has a new [exporter](https://github.com/hipages/php-fpm_exporter) to monitor PHP-FPM processes, see [#240394](https://github.com/NixOS/nixpkgs/pull/240394) for more details.
141142- `programs.gnupg.agent.pinentryFlavor` is now set in `/etc/gnupg/gpg-agent.conf`, and will no longer take precedence over a `pinentry-program` set in `~/.gnupg/gpg-agent.conf`.
00143144## Nixpkgs internals {#sec-release-23.11-nixpkgs-internals}
145
···3435- [ebusd](https://ebusd.eu), a daemon for handling communication with eBUS devices connected to a 2-wire bus system (“energy bus” used by numerous heating systems). Available as [services.ebusd](#opt-services.ebusd.enable).
3637+- [systemd-sysupdate](https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html), atomically updates the host OS, container images, portable service images or other sources. Available as [systemd.sysupdate](opt-systemd.sysupdate).
3839## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
40···141- `services.prometheus.exporters` has a new [exporter](https://github.com/hipages/php-fpm_exporter) to monitor PHP-FPM processes, see [#240394](https://github.com/NixOS/nixpkgs/pull/240394) for more details.
142143- `programs.gnupg.agent.pinentryFlavor` is now set in `/etc/gnupg/gpg-agent.conf`, and will no longer take precedence over a `pinentry-program` set in `~/.gnupg/gpg-agent.conf`.
144+145+- `wrapHelm` now exposes `passthru.pluginsDir` which can be passed to `helmfile`. For convenience, a top-level package `helmfile-wrapped` has been added, which inherits `passthru.pluginsDir` from `kubernetes-helm-wrapped`. See [#217768](https://github.com/NixOS/nixpkgs/issues/217768) for details.
146147## Nixpkgs internals {#sec-release-23.11-nixpkgs-internals}
148
···176 description = lib.mdDoc ''
177 Extra paperless config options.
178179- See [the documentation](https://paperless-ngx.readthedocs.io/en/latest/configuration.html)
180 for available options.
181182 Note that some options such as `PAPERLESS_CONSUMER_IGNORE_PATTERN` expect JSON values. Use `builtins.toJSON` to ensure proper quoting.
···176 description = lib.mdDoc ''
177 Extra paperless config options.
178179+ See [the documentation](https://docs.paperless-ngx.com/configuration/)
180 for available options.
181182 Note that some options such as `PAPERLESS_CONSUMER_IGNORE_PATTERN` expect JSON values. Use `builtins.toJSON` to ensure proper quoting.
···1+{ config, lib, pkgs, utils, ... }:
2+3+let
4+ cfg = config.systemd.sysupdate;
5+6+ format = pkgs.formats.ini { };
7+8+ listOfDefinitions = lib.mapAttrsToList
9+ (name: format.generate "${name}.conf")
10+ (lib.filterAttrs (k: _: !(lib.hasPrefix "_" k)) cfg.transfers);
11+12+ definitionsDirectory = pkgs.runCommand "sysupdate.d" { } ''
13+ mkdir -p $out
14+ ${(lib.concatStringsSep "\n"
15+ (map (pkg: "cp ${pkg} $out/${pkg.name}") listOfDefinitions)
16+ )}
17+ '';
18+in
19+{
20+ options.systemd.sysupdate = {
21+22+ enable = lib.mkEnableOption (lib.mdDoc "systemd-sysupdate") // {
23+ description = lib.mdDoc ''
24+ Atomically update the host OS, container images, portable service
25+ images or other sources.
26+27+ If enabled, updates are triggered in regular intervals via a
28+ `systemd.timer` unit.
29+30+ Please see
31+ <https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html>
32+ for more details.
33+ '';
34+ };
35+36+ timerConfig = utils.systemdUtils.unitOptions.timerOptions.options.timerConfig // {
37+ default = { };
38+ description = lib.mdDoc ''
39+ The timer configuration for performing the update.
40+41+ By default, the upstream configuration is used:
42+ <https://github.com/systemd/systemd/blob/main/units/systemd-sysupdate.timer>
43+ '';
44+ };
45+46+ reboot = {
47+ enable = lib.mkEnableOption (lib.mdDoc "automatically rebooting after an update") // {
48+ description = lib.mdDoc ''
49+ Whether to automatically reboot after an update.
50+51+ If set to `true`, the system will automatically reboot via a
52+ `systemd.timer` unit but only after a new version was installed.
53+54+ This uses a unit completely separate from the one performing the
55+ update because it is typically advisable to download updates
56+ regularly while the system is up, but delay reboots until the
57+ appropriate time (i.e. typically at night).
58+59+ Set this to `false` if you do not want to reboot after an update. This
60+ is useful when you update a container image or another source where
61+ rebooting is not necessary in order to finalize the update.
62+ '';
63+ };
64+65+ timerConfig = utils.systemdUtils.unitOptions.timerOptions.options.timerConfig // {
66+ default = { };
67+ description = lib.mdDoc ''
68+ The timer configuration for rebooting after an update.
69+70+ By default, the upstream configuration is used:
71+ <https://github.com/systemd/systemd/blob/main/units/systemd-sysupdate-reboot.timer>
72+ '';
73+ };
74+ };
75+76+ transfers = lib.mkOption {
77+ type = with lib.types; attrsOf format.type;
78+ default = { };
79+ example = {
80+ "10-uki.conf" = {
81+ Transfer = {
82+ ProtectVersion = "%A";
83+ };
84+85+ Source = {
86+ Type = "url-file";
87+ Path = "https://download.example.com/";
88+ MatchPattern = "nixos_@v.efi.xz";
89+ };
90+91+ Target = {
92+ Type = "regular-file";
93+ Path = "/EFI/Linux";
94+ PathRelativeTo = "boot";
95+ MatchPattern = ''
96+ nixos_@v+@l-@d.efi"; \
97+ nixos_@v+@l.efi \
98+ nixos_@v.efi
99+ '';
100+ Mode = "0444";
101+ TriesLeft = 3;
102+ TriesDone = 0;
103+ InstancesMax = 2;
104+ };
105+ };
106+ };
107+ description = lib.mdDoc ''
108+ Specify transfers as a set of the names of the transfer files as the
109+ key and the configuration as its value. The configuration can use all
110+ upstream options. See
111+ <https://www.freedesktop.org/software/systemd/man/sysupdate.d.html>
112+ for all available options.
113+ '';
114+ };
115+116+ };
117+118+ config = lib.mkIf cfg.enable {
119+120+ systemd.additionalUpstreamSystemUnits = [
121+ "systemd-sysupdate.service"
122+ "systemd-sysupdate.timer"
123+ "systemd-sysupdate-reboot.service"
124+ "systemd-sysupdate-reboot.timer"
125+ ];
126+127+ systemd.timers = {
128+ "systemd-sysupdate" = {
129+ wantedBy = [ "timers.target" ];
130+ timerConfig = cfg.timerConfig;
131+ };
132+ "systemd-sysupdate-reboot" = lib.mkIf cfg.reboot.enable {
133+ wantedBy = [ "timers.target" ];
134+ timerConfig = cfg.reboot.timerConfig;
135+ };
136+ };
137+138+ environment.etc."sysupdate.d".source = definitionsDirectory;
139+ };
140+141+ meta.maintainers = with lib.maintainers; [ nikstur ];
142+}
···40 "-DBUILD_SHARED_LIBS=ON"
41 "-DBUILD_OBJECT_LIBS=OFF"
42 "-DJSONCPP_WITH_CMAKE_PACKAGE=ON"
043 ]
44 # the test's won't compile if secureMemory is used because there is no
45 # comparison operators and conversion functions between
46 # std::basic_string<..., Json::SecureAllocator<char>> vs.
47 # std::basic_string<..., [default allocator]>
48- ++ lib.optional ((stdenv.buildPlatform != stdenv.hostPlatform) || secureMemory) "-DJSONCPP_WITH_TESTS=OFF"
49- ++ lib.optional (!enableStatic) "-DBUILD_STATIC_LIBS=OFF";
50-51- # this is fixed and no longer necessary in 1.9.5 but there they use
52- # memset_s without switching to a different c++ standard in the cmake files
53- postInstall = lib.optionalString enableStatic ''
54- (cd $out/lib && ln -sf libjsoncpp_static.a libjsoncpp.a)
55- '';
5657 meta = with lib; {
58 homepage = "https://github.com/open-source-parsers/jsoncpp";
···40 "-DBUILD_SHARED_LIBS=ON"
41 "-DBUILD_OBJECT_LIBS=OFF"
42 "-DJSONCPP_WITH_CMAKE_PACKAGE=ON"
43+ "-DBUILD_STATIC_LIBS=${if enableStatic then "ON" else "OFF"}"
44 ]
45 # the test's won't compile if secureMemory is used because there is no
46 # comparison operators and conversion functions between
47 # std::basic_string<..., Json::SecureAllocator<char>> vs.
48 # std::basic_string<..., [default allocator]>
49+ ++ lib.optional ((stdenv.buildPlatform != stdenv.hostPlatform) || secureMemory) "-DJSONCPP_WITH_TESTS=OFF";
00000005051 meta = with lib; {
52 homepage = "https://github.com/open-source-parsers/jsoncpp";
···321 echo "tested $binCount binCount: $ignoredCount ignored, $brokenCount broken, $failedCount failed"
322 [[ $failedCount = 0 ]]
323 '';
324+325+ # verify that the precomputed licensing information in default.nix
326+ # does indeed match the metadata of the individual packages.
327+ #
328+ # This is part of the test suite (and not the normal evaluation) to save
329+ # time for "normal" evaluations. To be more in line with the other tests, this
330+ # also builds a derivation, even though it is essentially an eval-time assertion.
331+ licenses =
332+ let
333+ concatLicenses = builtins.foldl' (acc: el: if builtins.elem el acc then acc else acc ++ [ el ]);
334+ # converts a license to its attribute name in lib.licenses
335+ licenseToAttrName = license:
336+ builtins.head (builtins.attrNames
337+ (lib.filterAttrs (n: v: license == v) lib.licenses));
338+ lt = (a: b: a < b);
339+340+ savedLicenses = scheme: scheme.meta.license;
341+ savedLicensesAttrNames = scheme: map licenseToAttrName (savedLicenses scheme);
342+343+ correctLicenses = scheme: builtins.foldl'
344+ (acc: pkg: concatLicenses acc (lib.toList (pkg.meta.license or [])))
345+ []
346+ scheme.passthru.packages;
347+ correctLicensesAttrNames = scheme:
348+ lib.sort lt
349+ (map licenseToAttrName (correctLicenses scheme));
350+351+ hasLicenseMismatch = scheme:
352+ (lib.isDerivation scheme) &&
353+ (savedLicensesAttrNames scheme) != (correctLicensesAttrNames scheme);
354+ incorrectSchemes = lib.filterAttrs
355+ (n: hasLicenseMismatch)
356+ texlive.combined;
357+ prettyPrint = name: scheme:
358+ ''
359+ license info for ${name} is incorrect! Note that order is enforced.
360+ saved: [ ${lib.concatStringsSep " " (savedLicensesAttrNames scheme)} ]
361+ correct: [ ${lib.concatStringsSep " " (correctLicensesAttrNames scheme)} ]
362+ '';
363+ errorText = lib.concatStringsSep "\n\n" (lib.mapAttrsToList prettyPrint incorrectSchemes);
364+ in
365+ runCommand "texlive-test-license" {
366+ inherit errorText;
367+ }
368+ (if (incorrectSchemes == {})
369+ then "echo everything is fine! > $out"
370+ else ''
371+ echo "$errorText"
372+ false
373+ '');
374}
···72the same output. Should those assumptions not hold, remove the previous fixed
73hashes for the relevant package, or for all packages.
740000000000000000075### Commit changes
7677Commit the updated `tlpdb.nix` and `fixed-hashes.nix` to the repository with
···72the same output. Should those assumptions not hold, remove the previous fixed
73hashes for the relevant package, or for all packages.
7475+### Updating the licensing information
76+77+The license of each package in texlive is automatically extracted from texlive's
78+texlive.tlpdb into tlpdb.nix. The combined licenses of the schemes is stored
79+separately in `default.nix` and must be kept in sync with the licenses of the
80+actual contents of these schemes. Whether this is the case can be verified with the
81+`pkgs.tests.texlive.licenses` test. In case of a mismatch, copy the “correct”
82+license lists reported by the test into `default.nix`.
83+84+### Running the testsuite
85+86+There are a some other useful tests that haven't been mentioned before. Build them with
87+```
88+nix-build ../../../../.. -A tests.texlive --no-out-link
89+```
90+91+92### Commit changes
9394Commit the updated `tlpdb.nix` and `fixed-hashes.nix` to the repository with
+27-1
pkgs/tools/typesetting/tex/texlive/default.nix
···43 # it seems to need it to transform fonts
44 xdvi.deps = (orig.xdvi.deps or []) ++ [ "metafont" ];
45046 # tlpdb lists license as "unknown", but the README says lppl13: http://mirrors.ctan.org/language/arabic/arabi-add/README
47 arabi-add.license = [ "lppl13c" ];
48···254255 # Pre-defined combined packages for TeX Live schemes,
256 # to make nix-env usage more comfortable and build selected on Hydra.
257- combined = with lib; recurseIntoAttrs (
000000000000000000000000258 mapAttrs
259 (pname: attrs:
260 addMetaAttrs rec {
261 description = "TeX Live environment for ${pname}";
262 platforms = lib.platforms.all;
263 maintainers = with lib.maintainers; [ veprbl ];
0264 }
265 (combine {
266 ${pname} = attrs;
···43 # it seems to need it to transform fonts
44 xdvi.deps = (orig.xdvi.deps or []) ++ [ "metafont" ];
4546+ # TODO: remove when updating to texlive-2023, metadata has been corrected in the TeX catalogue
47 # tlpdb lists license as "unknown", but the README says lppl13: http://mirrors.ctan.org/language/arabic/arabi-add/README
48 arabi-add.license = [ "lppl13c" ];
49···255256 # Pre-defined combined packages for TeX Live schemes,
257 # to make nix-env usage more comfortable and build selected on Hydra.
258+ combined = with lib;
259+ let
260+ # these license lists should be the sorted union of the licenses of the packages the schemes contain.
261+ # The correctness of this collation is tested by tests.texlive.licenses
262+ licenses = with lib.licenses; {
263+ scheme-basic = [ free gfl gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ];
264+ scheme-context = [ bsd2 bsd3 cc-by-sa-40 free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21
265+ lppl1 lppl13c mit ofl publicDomain x11 ];
266+ scheme-full = [ artistic1 artistic1-cl8 asl20 bsd2 bsd3 bsdOriginal cc-by-10 cc-by-40 cc-by-sa-10 cc-by-sa-20
267+ cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl1Plus gpl2 gpl2Plus gpl3 gpl3Plus isc knuth
268+ lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ];
269+ scheme-gust = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2
270+ gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ];
271+ scheme-infraonly = [ gpl2 lgpl21 ];
272+ scheme-medium = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only
273+ free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl
274+ publicDomain x11 ];
275+ scheme-minimal = [ free gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ];
276+ scheme-small = [ asl20 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth
277+ lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ];
278+ scheme-tetex = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-10 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0
279+ fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a
280+ lppl13c mit ofl publicDomain x11];
281+ };
282+ in recurseIntoAttrs (
283 mapAttrs
284 (pname: attrs:
285 addMetaAttrs rec {
286 description = "TeX Live environment for ${pname}";
287 platforms = lib.platforms.all;
288 maintainers = with lib.maintainers; [ veprbl ];
289+ license = licenses.${pname};
290 }
291 (combine {
292 ${pname} = attrs;
···377 zake = throw "zake has been removed because it is abandoned"; # added 2023-06-20
378 zc-buildout221 = zc-buildout; # added 2021-07-21
379 zc_buildout_nix = throw "zc_buildout_nix was pinned to a version no longer compatible with other modules";
0380})
···377 zake = throw "zake has been removed because it is abandoned"; # added 2023-06-20
378 zc-buildout221 = zc-buildout; # added 2021-07-21
379 zc_buildout_nix = throw "zc_buildout_nix was pinned to a version no longer compatible with other modules";
380+ zope_broken = throw "zope_broken has been removed because it is obsolete and not needed in zodb>=3.10"; # added 2023-07-26
381})