Commit 794796910f
794796910f5fdc942f064f5e9e28a93b722586f5
parent: 439734b5d0
Verified · cmc
cmc <hello@cleberg.net> · 2026-08-25T15:33:14Z
Recognize 0BSD; stop mislabeling it as ISC
ISC is the 0BSD grant plus the notice-retention clause, so the old
permission-sentence marker matched both. ISC now matches on the clause,
0BSD on the title or the bare grant. License text is whitespace-collapsed
before matching so markers survive line wraps.
e2e/design_test.go
+3 −2
| @@ -55,12 +55,13 @@ func TestReadmeRelativeLinks(t *testing.T) { |
| 55 | 55 | } |
| 56 | 56 | // Explore rows carry topics, license, and updated date. |
| 57 | 57 | inst.ssh(t, aliceKey, "", "repo", "topics", "add", "alice/site", "web") |
| 58 | | os.WriteFile(filepath.Join(dir, "LICENSE"), []byte("Permission to use, copy, modify, and/or distribute this software...\n"), 0o644) |
| 58 | // Bare 0BSD grant (no notice-retention clause), wrapped mid-sentence. |
| 59 | os.WriteFile(filepath.Join(dir, "LICENSE"), []byte("Permission to use, copy, modify,\nand/or distribute this software for any\npurpose with or without fee is hereby granted.\n"), 0o644) |
| 59 | 60 | mustGit(t, dir, env, "add", ".") |
| 60 | 61 | mustGit(t, dir, env, "commit", "-q", "-m", "license") |
| 61 | 62 | mustGit(t, dir, env, "push", "-q", "origin", "main") |
| 62 | 63 | _, body = inst.get(t, "/explore") |
| 63 | | for _, want := range []string{`href="/explore?q=web"`, "ISC", "updated 20"} { |
| 64 | for _, want := range []string{`href="/explore?q=web"`, "0BSD", "updated 20"} { |
| 64 | 65 | if !strings.Contains(body, want) { |
| 65 | 66 | t.Errorf("explore row missing %q", want) |
| 66 | 67 | } |
internal/httpd/readme.go
+8 −2
| @@ -23,7 +23,12 @@ var licenseChecks = []struct{ marker, name string }{ |
| 23 | 23 | {"BSD 3-Clause", "BSD-3-Clause"}, |
| 24 | 24 | {"BSD 2-Clause", "BSD-2-Clause"}, |
| 25 | 25 | {"Redistribution and use in source and binary forms", "BSD"}, |
| 26 | | {"Permission to use, copy, modify, and/or distribute", "ISC"}, |
| 26 | {"BSD Zero Clause License", "0BSD"}, |
| 27 | {"Zero Clause BSD", "0BSD"}, |
| 28 | // ISC is the 0BSD grant plus the notice-retention clause; match on the |
| 29 | // clause so title-less 0BSD files don't read as ISC. |
| 30 | {"hereby granted, provided that the above copyright notice", "ISC"}, |
| 31 | {"Permission to use, copy, modify, and/or distribute", "0BSD"}, |
| 27 | 32 | {"This is free and unencumbered software", "Unlicense"}, |
| 28 | 33 | {"CC0", "CC0"}, |
| 29 | 34 | } |
| @@ -36,7 +41,8 @@ func detectLicense(dir, ref string) string { |
| 36 | 41 | if err != nil { |
| 37 | 42 | continue |
| 38 | 43 | } |
| 39 | | text := string(raw) |
| 44 | // Collapse whitespace so markers match across line wraps. |
| 45 | text := strings.Join(strings.Fields(string(raw)), " ") |
| 40 | 46 | for _, c := range licenseChecks { |
| 41 | 47 | if strings.Contains(text, c.marker) { |
| 42 | 48 | return c.name |