on iko/ghcjs-patch-master help sign in
Spdx license expressions (#859)
07df700toonn
builder/comp-builder.nix+2−6
@@ -1,4 +1,4 @@
1−{ stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, compiler, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }:
1+{ pkgs, stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, compiler, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }:
2lib.makeOverridable (
2lib.makeOverridable (
3let self =
3let self =
4{ componentId
4{ componentId
@@ -295,11 +295,7 @@ let
295 meta = {
295 meta = {
296 homepage = package.homepage or "";
296 homepage = package.homepage or "";
297 description = package.synopsis or "";
297 description = package.synopsis or "";
298− license =
298+ license = haskellLib.cabalToNixpkgsLicense package.license;
299− let
300− license-map = import ../lib/cabal-licenses.nix lib;
301− in license-map.${package.license} or
302− (builtins.trace "WARNING: license \"${package.license}\" not found" license-map.LicenseRef-OtherLicense);
303 platforms = if platforms == null then stdenv.lib.platforms.all else platforms;
299 platforms = if platforms == null then stdenv.lib.platforms.all else platforms;
304 };
300 };
305
301
builder/setup-builder.nix+2−6
@@ -1,4 +1,4 @@
1−{ stdenv, lib, buildPackages, haskellLib, ghc, nonReinstallablePkgs, hsPkgs, makeSetupConfigFiles, pkgconfig }:
1+{ pkgs, stdenv, lib, buildPackages, haskellLib, ghc, nonReinstallablePkgs, hsPkgs, makeSetupConfigFiles, pkgconfig }:
2
2
3{ component, package, name, src, flags ? {}, revision ? null, patches ? [], defaultSetupSrc
3{ component, package, name, src, flags ? {}, revision ? null, patches ? [], defaultSetupSrc
4, preUnpack ? component.preUnpack, postUnpack ? component.postUnpack
4, preUnpack ? component.preUnpack, postUnpack ? component.postUnpack
@@ -55,11 +55,7 @@ let
55 meta = {
55 meta = {
56 homepage = package.homepage or "";
56 homepage = package.homepage or "";
57 description = package.synopsis or "";
57 description = package.synopsis or "";
58− license =
58+ license = haskellLib.cabalToNixpkgsLicense package.license;
59− let
60− license-map = import ../lib/cabal-licenses.nix lib;
61− in license-map.${package.license} or
62− (builtins.trace "WARNING: license \"${package.license}\" not found" license-map.LicenseRef-OtherLicense);
63 platforms = if component.platforms == null then stdenv.lib.platforms.all else component.platforms;
59 platforms = if component.platforms == null then stdenv.lib.platforms.all else component.platforms;
64 };
60 };
65
61
lib/cabal-licenses.nix+17−21
@@ -1,24 +1,20 @@
1−lib: with lib.licenses;
1+pkgs:
2−{ BSD-3-Clause = bsd3;
2+let licenses = import spdx/licenses.nix pkgs;
3− BSD-2-Clause = bsd2;
3+in licenses // {
4− MIT = mit;
5− "MPL-2.0" = mpl20;
6− ISC = isc;
7− "LGPL-2.1-only" = lgpl21;
8− "LGPL-3.0-only" = lgpl3;
9− "GPL-2.0-only" = gpl2;
10− "GPL-2.0-or-later" = gpl2Plus;
11− "GPL-3.0-only" = gpl3;
12− "AGPL-3.0-only" = agpl3;
13− "AGPL-3.0-or-later" = agpl3Plus;
14− "Apache-2.0" = asl20;
15− "GPL-2.0-or-later AND BSD-3-Clause" = [gpl2Plus bsd3];
16− "NCSA" = ncsa;
17 # Generic
4 # Generic
18− LicenseRef-Apache = "Apache";
5+ LicenseRef-PublicDomain = {
19− LicenseRef-GPL = "GPL";
6+ spdxId = "LicenseRef-PublicDomain";
20− LicenseRef-LGPL = "LGPL";
7+ shortName = "Public Domain";
21− LicenseRef-PublicDomain = publicDomain;
8+ fullName = "This work is dedicated to the Public Domain";
9+ url = "https://wikipedia.org/wiki/Public_domain";
10+ free = true;
11+ };
12+ LicenseRef-OtherLicense = {
22− LicenseRef-OtherLicense = null;
13+ spdxId = "LicenseRef-OtherLicense";
14+ shortName = "Other License";
15+ fullName = "Unidentified Other License";
16+ url = "https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/";
17+ free = false;
18+ };
23 NONE = null;
19 NONE = null;
24}
20}
lib/default.nix+3
@@ -274,6 +274,9 @@ in {
274 inherit pkgs;
274 inherit pkgs;
275 }) parseIndexState parseBlock;
275 }) parseIndexState parseBlock;
276
276
277+
278+ cabalToNixpkgsLicense = import ./spdx/cabal.nix pkgs;
279+
277 # This function is like
280 # This function is like
278 # `src + (if subDir == "" then "" else "/" + subDir)`
281 # `src + (if subDir == "" then "" else "/" + subDir)`
279 # however when `includeSiblings` is set it maintains
282 # however when `includeSiblings` is set it maintains
lib/spdx/cabal.nixnew file+19
@@ -0,0 +1,19 @@
1+let
2+ spdx = import ./parser.nix;
3+in pkgs:
4+with builtins;
5+let
6+ # For better performance these are not in the
7+ # let block below (probably helps by increasing
8+ # the sharing)
9+ license-map = import ../cabal-licenses.nix pkgs;
10+ otherLicenseWarning = lic:
11+ trace "WARNING: license \"${lic}\" not found"
12+ license-map.LicenseRef-OtherLicense;
13+in license:
14+let
15+ licenses = spdx.compound-expression license;
16+in if licenses == []
17+ then otherLicenseWarning license
18+ else map (lic: license-map.${lic} or (otherLicenseWarning lic))
19+ (pkgs.lib.unique (head licenses)._1)
lib/spdx/licenses.nixnew file+20
@@ -0,0 +1,20 @@
1+pkgs:
2+with builtins; let
3+ licensesJSON = fromJSON (replaceStrings
4+ [ "\\u0026" "\\u0027" "\\u003d" ]
5+ [ "&" "'" "=" ]
6+ (readFile "${pkgs.evalPackages.spdx-license-list-data}/json/licenses.json")
7+ );
8+ dropFour = s: substring 0 (stringLength s - 4) s;
9+ toSpdx = lic: with lic;
10+ { spdxId = licenseId
11+ ; shortName = licenseId
12+ ; fullName = name
13+ ; url = dropFour detailsUrl + "html"
14+ ; free = isOsiApproved
15+ ;
16+ };
17+ toNamedValue = lic: { name = lic.spdxId; value = lic; };
18+in
19+
20+listToAttrs (map (l: toNamedValue (toSpdx l)) licensesJSON.licenses)
lib/spdx/parser.nixnew file+115
@@ -0,0 +1,115 @@
1+let String = { mempty = ""; mappend = a: b: a + b; };
2+ List = { singleton = x: [x]; };
3+ pair = a: b: { _1 = a; _2 = b; };
4+ Pair = { pure = s: pair String.mempty s;
5+ mappend = a: b: pair (String.mappend a._1 b._1) b._2;
6+ map = f: p: pair (f p._1) p._2;
7+ };
8+ compose = f: g: x: f (g x);
9+in with builtins; rec {
10+ # Parser a = String -> [(a, String)]
11+ string = str: s:
12+ let strL = stringLength str;
13+ sL = stringLength s;
14+ in if str == substring 0 strL s
15+ then [ (pair str (substring strL sL s)) ]
16+ else [];
17+
18+ regex = capture_groups: re: s:
19+ let result = match "(${re})(.*)" s;
20+ in if result == null
21+ then []
22+ else [ (pair (elemAt result 0) (elemAt result (1 + capture_groups))) ];
23+
24+ # Left-biased choice
25+ choice = cs: s:
26+ if cs == []
27+ then []
28+ else let c = head cs;
29+ cs' = tail cs;
30+ result = c s;
31+ in if result == []
32+ then choice cs' s
33+ else result;
34+
35+ optional = p: s:
36+ let result = p s;
37+ in if result == []
38+ then [ (Pair.pure s) ]
39+ else result;
40+
41+ chain = ps: s:
42+ if ps == []
43+ then [ (Pair.pure s) ]
44+ else let p = head ps;
45+ ps' = tail ps;
46+ result = p s;
47+ in if result == []
48+ then []
49+ else let r = head result;
50+ rest = chain ps' r._2;
51+ in if rest == []
52+ then []
53+ else let r' = head rest;
54+ in [ (Pair.mappend r r') ];
55+
56+ idstring = regex 0 "[-\.0-9a-zA-Z]+";
57+
58+ license-ref = let documentref = chain [ (string "DocumentRef-")
59+ idstring
60+ (string ":")
61+ ];
62+ in chain [
63+ (optional documentref)
64+ (string "LicenseRef-")
65+ idstring
66+ ];
67+
68+ simple-expression = choice [ license-ref
69+ (chain [ idstring (string "+") ])
70+ idstring
71+ ];
72+
73+ compound-expression = let wrap = compose (map (Pair.map List.singleton));
74+ in choice [
75+ (s: let result = simple-expression s;
76+ in if result == []
77+ then []
78+ else let r = head result;
79+ rest = chain [(string " WITH ") idstring ] r._2;
80+ in if rest == []
81+ then []
82+ else [(pair r._1 (head rest)._2)]
83+ )
84+ (s: let result = simple-expression s;
85+ in if result == []
86+ then []
87+ else let r = head result;
88+ firstLicense = r._1;
89+ operator = choice [ (string " AND ")
90+ (string " OR ")
91+ ]
92+ r._2;
93+ in if operator == []
94+ then []
95+ else let s' = (head operator)._2;
96+ licenses = compound-expression s';
97+ in if licenses == []
98+ then []
99+ else let ls = head licenses;
100+ in [(pair ([firstLicense] ++ ls._1) ls._2)]
101+ )
102+ (wrap simple-expression)
103+ (s: let openParen = string "(" s;
104+ in if openParen == []
105+ then []
106+ else let result = compound-expression (head openParen)._2;
107+ in if result == []
108+ then []
109+ else let r = head result;
110+ closeParen = string ")" r._2;
111+ in if closeParen == []
112+ then []
113+ else [(pair r._1 (head closeParen)._2)])
114+ ];
115+}
lib/spdx/test.nixnew file+32
@@ -0,0 +1,32 @@
1+let spdx = import ./parser.nix;
2+in {
3+ idstringF = [ (spdx.idstring "$@#!$") ];
4+ idstringP = [ (spdx.idstring "blah") ];
5+
6+ license-refF = [ (spdx.license-ref "LicenseRef-$@#!$") ];
7+ license-refP = [ (spdx.license-ref "LicenseRef-blah")
8+ (spdx.license-ref "DocumentRef-beep:LicenseRef-boop")
9+ ];
10+
11+ simple-expressionF = [ (spdx.simple-expression "$@#!$") ];
12+ simple-expressionP = [
13+ (spdx.simple-expression "blah")
14+ (spdx.simple-expression "blah+")
15+ (spdx.simple-expression "LicenseRef-blah")
16+ (spdx.simple-expression "DocumentRef-beep:LicenseRef-boop")
17+ ];
18+
19+ compound-expressionF = [ (spdx.compound-expression "$@#!$") ];
20+ compound-expressionP = [
21+ (spdx.compound-expression "blah")
22+ (spdx.compound-expression "blah+")
23+ (spdx.compound-expression "LicenseRef-blah")
24+ (spdx.compound-expression "DocumentRef-beep:LicenseRef-boop")
25+ (spdx.compound-expression "(blah)")
26+ (spdx.compound-expression "beep OR boop")
27+ (spdx.compound-expression "beep AND boop")
28+ (spdx.compound-expression "beep WITH boop")
29+ (spdx.compound-expression "beep AND (boop OR blap)")
30+ (spdx.compound-expression "(beep AND ((boop OR ((blap)))))")
31+ ];
32+}
modules/configuration-nix.nix+7
@@ -15,4 +15,11 @@
15 pkgs.xorg.libXScrnSaver
15 pkgs.xorg.libXScrnSaver
16 pkgs.xorg.libXinerama
16 pkgs.xorg.libXinerama
17 ];
17 ];
18+
19+ # These packages have `license: LGPL` in their .cabal file, but
20+ # do not specify the version. Setting the version here on
21+ # examination of the license files included in the packages.
22+ packages.hscolour.package.license = pkgs.lib.mkForce "LGPL-2.1-only";
23+ packages.cpphs.package.license = pkgs.lib.mkForce "LGPL-2.1-only";
24+ packages.polyparse.package.license = pkgs.lib.mkForce "LGPL-2.1-only";
18}
25}