diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | cmd/generate/imworkingon.html.tmpl (renamed from plan.html.tmpl) | 0 | ||||
-rw-r--r-- | cmd/generate/main.go | 84 | ||||
-rw-r--r-- | cmd/generate/src_contribs.go | 103 | ||||
-rw-r--r-- | cmd/generate/src_tags.go | 24 | ||||
-rw-r--r-- | cmd/generate/src_upstreams.go | 46 | ||||
-rw-r--r-- | contribs.yml | 164 | ||||
-rw-r--r-- | gen.go | 189 | ||||
-rw-r--r-- | tags.yml | 27 |
10 files changed, 356 insertions, 287 deletions
@@ -1 +1 @@ -/plan.html +/imworkingon.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b3095ec --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +imworkingon.html: FORCE + go run ./cmd/generate + +.PHONY: FORCE diff --git a/plan.html.tmpl b/cmd/generate/imworkingon.html.tmpl index 54d9431..54d9431 100644 --- a/plan.html.tmpl +++ b/cmd/generate/imworkingon.html.tmpl diff --git a/cmd/generate/main.go b/cmd/generate/main.go new file mode 100644 index 0000000..ce5ce0d --- /dev/null +++ b/cmd/generate/main.go @@ -0,0 +1,84 @@ +package main + +import ( + "bytes" + _ "embed" + "fmt" + "os" + "strings" + + "html/template" + + "github.com/yuin/goldmark" +) + +func MarkdownToHTML(md string) (template.HTML, error) { + var html strings.Builder + if err := goldmark.Convert([]byte(md), &html); err != nil { + return template.HTML(""), err + } + return template.HTML(html.String()), nil +} + +var githubProjects = map[string]string{ + "flori/json": "ruby-json", +} + +func main() { + if err := mainWithError(); err != nil { + fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) + os.Exit(1) + } +} + +//go:embed imworkingon.html.tmpl +var htmlTmplStr string + +func mainWithError() error { + contribs, err := ReadContribs("contribs.yml") + if err != nil { + return err + } + tags, err := ReadUpstreams("tags.yml") + if err != nil { + return err + } + upstreams, err := ReadUpstreams("upstreams.yml") + if err != nil { + return err + } + tmpl := template.Must(template.New("imworkingon.html"). + Funcs(template.FuncMap{ + "md2html": MarkdownToHTML, + "getUpstream": func(c Contribution) Upstream { + // First try any of the documented upstreams. + for _, cURL := range c.URLs { + for _, upstream := range upstreams { + for _, uURL := range upstream.URLs { + prefix := uURL + if !strings.HasSuffix(prefix, "/") { + prefix += "/" + } + if cURL == uURL || strings.HasPrefix(cURL, prefix) { + return upstream + } + } + } + } + return Upstream{URLs: []string{c.URLs[0]}, Name: "???"} + }, + }). + Parse(htmlTmplStr)) + var out bytes.Buffer + if err := tmpl.Execute(&out, map[string]any{ + "Contribs": contribs, + "Tags": tags, + "upstreams": upstreams, + }); err != nil { + return err + } + if err := os.WriteFile("plan.html", out.Bytes(), 0666); err != nil { + return err + } + return nil +} diff --git a/cmd/generate/src_contribs.go b/cmd/generate/src_contribs.go new file mode 100644 index 0000000..eaff24b --- /dev/null +++ b/cmd/generate/src_contribs.go @@ -0,0 +1,103 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "regexp" + "strings" + "time" + + "sigs.k8s.io/yaml" +) + +type Contribution struct { + URLs []string `json:"urls"` + Tags []string `json:"tags"` + SponsoredBy string `json:"sponsored-by"` + Desc string `json:"desc"` + + SubmittedAt time.Time `json:"submitted-at"` +} + +func ReadContribs(filename string) ([]Contribution, error) { + bs, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + var ret []Contribution + if err := yaml.UnmarshalStrict(bs, &ret); err != nil { + return nil, err + } + for i := range ret { + contrib := ret[i] + if err := contrib.Fill(); err != nil { + return nil, err + } + ret[i] = contrib + } + return ret, nil +} + +func (c *Contribution) Fill() error { + var err error + if c.SubmittedAt.IsZero() { + c.SubmittedAt, err = c.getSubmittedAt() + if err != nil { + return err + } + } + return nil +} + +var ( + reGitHubPR = regexp.MustCompile(`^https://github.com/([^/?#]+)/([^/?#]+)/pull/([0-9]+)(?:\?[^#]*)?(?:#.*)?$`) + rePiperMailDate = regexp.MustCompile(`^\s*<I>([^<]+)</I>\s*$`) +) + +func (c Contribution) getSubmittedAt() (time.Time, error) { + if m := reGitHubPR.FindStringSubmatch(c.URLs[0]); m != nil { + user := m[1] + repo := m[2] + prnum := m[3] + resp, err := http.Get("https://api.github.com/repos/" + user + "/" + repo + "/pulls/" + prnum) + if err != nil { + return time.Time{}, err + } + if resp.StatusCode != http.StatusOK { + return time.Time{}, fmt.Errorf("unexpected HTTP status: %v", resp.Status) + } + jsonBytes, err := io.ReadAll(resp.Body) + if err != nil { + return time.Time{}, err + } + var obj struct { + CreatedAt time.Time `json:"created_at"` + } + if err := json.Unmarshal(jsonBytes, &obj); err != nil { + return time.Time{}, err + } + return obj.CreatedAt, nil + } + if strings.Contains(c.URLs[0], "/pipermail/") { + resp, err := http.Get(c.URLs[0]) + if err != nil { + return time.Time{}, err + } + if resp.StatusCode != http.StatusOK { + return time.Time{}, fmt.Errorf("unexpected HTTP status: %v", resp.Status) + } + htmlBytes, err := io.ReadAll(resp.Body) + if err != nil { + return time.Time{}, err + } + for _, line := range strings.Split(string(htmlBytes), "\n") { + if m := rePiperMailDate.FindStringSubmatch(line); m != nil { + return time.Parse(time.UnixDate, m[1]) + } + } + } + return time.Time{}, fmt.Errorf("idk how to get timestamps for %q", c.URLs[0]) +} diff --git a/cmd/generate/src_tags.go b/cmd/generate/src_tags.go new file mode 100644 index 0000000..497f37e --- /dev/null +++ b/cmd/generate/src_tags.go @@ -0,0 +1,24 @@ +package main + +import ( + "os" + + "sigs.k8s.io/yaml" +) + +type TagInfo struct { + PrettyName string `json:"prettyName"` + Desc string `json:"desc"` +} + +func ReadTags(filename string) (map[string]TagInfo, error) { + bs, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + var ret map[string]TagInfo + if err := yaml.UnmarshalStrict(bs, &ret); err != nil { + return nil, err + } + return ret, nil +} diff --git a/cmd/generate/src_upstreams.go b/cmd/generate/src_upstreams.go new file mode 100644 index 0000000..1ea7750 --- /dev/null +++ b/cmd/generate/src_upstreams.go @@ -0,0 +1,46 @@ +package main + +import ( + _ "embed" + "net/url" + "os" + "path" + + "sigs.k8s.io/yaml" +) + +type Upstream struct { + URLs []string `json:"urls"` + Name string `json:"name"` + Desc string `json:"desc"` +} + +func ReadUpstreams(filename string) ([]Upstream, error) { + bs, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + var ret []Upstream + if err := yaml.UnmarshalStrict(bs, &ret); err != nil { + return []Upstream{}, err + } + for i := range ret { + upstream := ret[i] + if err := upstream.Fill(); err != nil { + return nil, err + } + ret[i] = upstream + } + return ret, nil +} + +func (upstream *Upstream) Fill() error { + if upstream.Name == "" { + u, err := url.Parse(upstream.URLs[0]) + if err != nil { + return err + } + _, upstream.Name = path.Split(path.Clean(u.Path)) + } + return nil +} diff --git a/contribs.yml b/contribs.yml index 20ec3aa..6620ea7 100644 --- a/contribs.yml +++ b/contribs.yml @@ -1,100 +1,70 @@ -tags: - docs: - prettyName: Documentation - desc: | - I'm working to improve documentation for GNU/Linux, but more - than that I'm working to improve the forms of documentation that - more skilled technical writers might be afraid or incapable of - working on: `--help` text, generated documentation, and auditing - documentation against the source code to make sure that it is - accurate and complete. - ARM: - prettyName: ARM support - desc: | - Not that folks can't use GNU/Linux on ARM (obviously, the - Raspberry Pi has been a huge success), but there's still a lot - more friction to using GNU/Linux on ARM compared to x86. I'm - working on that. - GI: - prettyName: GObject Introspection - desc: | - GObject Introspection (which is a terrible name for what it is, - btw) is a cross-(language-runtime) object system. GObject was - an object system for C that game out of GTK+, and then GObject - Introspection was created as a way to specify the ABI for - working with an object, so that GObjects could be used from - other languages. I think that GObject Introspection is a really - cool technology that can be the basis of reducing friction - between languages, but it needs better/more-ubiquitous tooling. +- urls: [https://github.com/flori/json/pull/567] + tags: [Ruby, JSON, SoftwareFreedom] + desc: | + ruby-json contains code that is not Free under the FSF's + definition, not Open Source under the OSI's definition, and not + GPL-compatible. This has coused much consternation among folks + who care about any of those 3 things. -contributions: - - urls: [https://github.com/flori/json/pull/567] - tags: [Ruby, JSON, SoftwareFreedom] - desc: | - ruby-json contains code that is not Free under the FSF's - definition, not Open Source under the OSI's definition, and not - GPL-compatible. This has coused much consternation among folks - who care about any of those 3 things. + This PR replaces that non-Free code with Free code, removing + friction for Ruby users on GNU/Linux distros that care about those + 3 things. +- urls: [https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/328] + tags: [ARM] + sponsored-by: Umorpha Systems + desc: | + To do its work, mkinitcpio needs to know the version number of the + Linux kernel that it is generating an image for; the normal way + that it knows this is to sniff the version number from the kernel + file. However, it fails to sniff the version number from ARM + zImage kernels, which means that Arch Linux ARM and Parabola for + ARM need to resort to hacks to get mkinitcpio to work right. - This PR replaces that non-Free code with Free code, removing - friction for Ruby users on GNU/Linux distros that care about - those 3 things. - - urls: [https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/328] - tags: [ARM] - sponsored-by: Umorpha Systems - desc: | - To do its work, mkinitcpio needs to know the version number of - the Linux kernel that it is generating an image for; the normal - way that it knows this is to sniff the version number from the - kernel file. However, it fails to sniff the version number from - ARM zImage kernels, which means that Arch Linux ARM and Parabola - for ARM need to resort to hacks to get mkinitcpio to work right. + This PR removes that friction by teaching mkinitcpio to understand + ARM zImage files. +- urls: [https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/277] + sponsored-by: Umorpha Systems + desc: | + One of the things going on in the secure-boot world is moving + toward "Unified Kernel Images" (UKI), which are when the kernel + and the init-ramdisk are bundled together into a single file to + reduce the risk of a compromised init-ramdisk being able to + compromise a secured kernel. This PR reduces friction when using + mkinitcpio to generate images directly as UKI without generating a + plain init-ramdisk first. +- urls: + - https://mailman.astron.com/pipermail/file/2024-April/001335.html + - https://github.com/file/file/commit/cf139abf35d07ebfd0c3edcab2fc400a211c0fbb + tags: [ARM] + desc: | + This PR improves its ability to detect information about Linux + kernel ARM zImage files. +- urls: + - https://mailman.astron.com/pipermail/file/2024-March/001327.html + - https://github.com/file/file/commit/3b92878ee277a6b6c0a37429e9edf5e5b55fcdd4 + tags: [docs] + desc: | + To do this, `file` reads a "magic" file that describes the magic + numbers that it might see in a file. This PR fixes a mistake in + the `magic(5)` manual for writing such files. +- urls: [https://github.com/diamondburned/gotk4/pull/140] + tags: [GI, docs] + desc: | + The not-quite-markdown format that `.gir` files use for + documentation is under-specified and hard to parse. Right now I'm + focusing on how to properly parse it, so that we can have + top-notch language-specific documentation for GI libraries. - This PR removes that friction by teaching mkinitcpio to - understand ARM zImage files. - - urls: [https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/277] - sponsored-by: Umorpha Systems - desc: | - One of the things going on in the secure-boot world is moving - toward "Unified Kernel Images" (UKI), which are when the kernel - and the init-ramdisk are bundled together into a single file to - reduce the risk of a compromised init-ramdisk being able to - compromise a secured kernel. This PR reduces friction when - using mkinitcpio to generate images directly as UKI without - generating a plain init-ramdisk first. - - urls: - - https://mailman.astron.com/pipermail/file/2024-April/001335.html - - https://github.com/file/file/commit/cf139abf35d07ebfd0c3edcab2fc400a211c0fbb - tags: [ARM] - desc: | - This PR improves its ability to detect information about Linux - kernel ARM zImage files. - - urls: - - https://mailman.astron.com/pipermail/file/2024-March/001327.html - - https://github.com/file/file/commit/3b92878ee277a6b6c0a37429e9edf5e5b55fcdd4 - tags: [docs] - desc: | - To do this, `file` reads a "magic" file that describes the magic - numbers that it might see in a file. This PR fixes a mistake in - the `magic(5)` manual for writing such files. - - urls: [https://github.com/diamondburned/gotk4/pull/140] - tags: [GI, docs] - desc: | - The not-quite-markdown format that `.gir` files use for - documentation is under-specified and hard to parse. Right now - I'm focusing on how to properly parse it, so that we can have - top-notch language-specific documentation for GI libraries. - - This PR is laying the groundwork for the new parser. - - urls: - - https://lists.ozlabs.org/pipermail/linux-erofs/2023-November/009765.html - - https://github.com/erofs/erofs-utils/commit/f528b82ffbcb15484a7195c1a1d08ece0ff67350 - - https://github.com/erofs/erofs-utils/commit/197e3294bcdf93f37d12989cd830a33c055b1a53 - - https://github.com/erofs/erofs-utils/commit/f97311883337eb7e0ded55e60995e6599eba73e5 - tags: [docs] - sponsored-by: Umorpha Systems - desc: | - This patchset improves the `--help` documentation and - man-pages the EroFS userspace tools, and reduces friction by - having `fsck.erofs` accept common command line flags that fsck - implementions for other filesystems take. + This PR is laying the groundwork for the new parser. +- urls: + - https://lists.ozlabs.org/pipermail/linux-erofs/2023-November/009765.html + - https://github.com/erofs/erofs-utils/commit/f528b82ffbcb15484a7195c1a1d08ece0ff67350 + - https://github.com/erofs/erofs-utils/commit/197e3294bcdf93f37d12989cd830a33c055b1a53 + - https://github.com/erofs/erofs-utils/commit/f97311883337eb7e0ded55e60995e6599eba73e5 + tags: [docs] + sponsored-by: Umorpha Systems + desc: | + This patchset improves the `--help` documentation and man-pages + the EroFS userspace tools, and reduces friction by having + `fsck.erofs` accept common command line flags that fsck + implementions for other filesystems take. @@ -1,189 +0,0 @@ -package main - -import ( - "bytes" - _ "embed" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path" - "regexp" - "sigs.k8s.io/yaml" - "strings" - "time" - - "github.com/yuin/goldmark" - "html/template" -) - -type Contribs struct { - Tags map[string]TagInfo `json:"tags"` - Contributions []Contribution `json:"contributions"` -} - -type TagInfo struct { - PrettyName string `json:"prettyName"` - Desc string `json:"desc"` -} - -type Contribution struct { - URLs []string `json:"urls"` - Tags []string `json:"tags"` - SponsoredBy string `json:"sponsored-by"` - Desc string `json:"desc"` -} - -var ( - reGitHubPR = regexp.MustCompile(`^https://github.com/([^/?#]+)/([^/?#]+)/pull/([0-9]+)(?:\?[^#]*)?(?:#.*)?$`) - rePiperMailDate = regexp.MustCompile(`^\s*<I>([^<]+)</I>\s*$`) -) - -func (c Contribution) SubmittedAt() (time.Time, error) { - if m := reGitHubPR.FindStringSubmatch(c.URLs[0]); m != nil { - user := m[1] - repo := m[2] - prnum := m[3] - resp, err := http.Get("https://api.github.com/repos/" + user + "/" + repo + "/pulls/" + prnum) - if err != nil { - return time.Time{}, err - } - if resp.StatusCode != http.StatusOK { - return time.Time{}, fmt.Errorf("unexpected HTTP status: %v", resp.Status) - } - jsonBytes, err := io.ReadAll(resp.Body) - if err != nil { - return time.Time{}, err - } - var obj struct { - CreatedAt time.Time `json:"created_at"` - } - if err := json.Unmarshal(jsonBytes, &obj); err != nil { - return time.Time{}, err - } - return obj.CreatedAt, nil - } - if strings.Contains(c.URLs[0], "/pipermail/") { - resp, err := http.Get(c.URLs[0]) - if err != nil { - return time.Time{}, err - } - if resp.StatusCode != http.StatusOK { - return time.Time{}, fmt.Errorf("unexpected HTTP status: %v", resp.Status) - } - htmlBytes, err := io.ReadAll(resp.Body) - if err != nil { - return time.Time{}, err - } - for _, line := range strings.Split(string(htmlBytes), "\n") { - if m := rePiperMailDate.FindStringSubmatch(line); m != nil { - return time.Parse(time.UnixDate, m[1]) - } - } - } - return time.Time{}, nil //fmt.Errorf("idk how to check") -} - -func ReadContribs(filename string) (Contribs, error) { - bs, err := os.ReadFile(filename) - if err != nil { - return Contribs{}, err - } - var ret Contribs - if err := yaml.UnmarshalStrict(bs, &ret); err != nil { - return Contribs{}, err - } - return ret, nil -} - -type Upstream struct { - URLs []string `json:"urls"` - Name string `json:"name"` - Desc string `json:"desc"` -} - -func ReadUpstreams(filename string) ([]Upstream, error) { - bs, err := os.ReadFile(filename) - if err != nil { - return nil, err - } - var ret []Upstream - if err := yaml.UnmarshalStrict(bs, &ret); err != nil { - return []Upstream{}, err - } - for i := range ret { - if ret[i].Name == "" { - u, err := url.Parse(ret[i].URLs[0]) - if err != nil { - return nil, err - } - _, ret[i].Name = path.Split(path.Clean(u.Path)) - } - } - return ret, nil -} - -func MarkdownToHTML(md string) (template.HTML, error) { - var html strings.Builder - if err := goldmark.Convert([]byte(md), &html); err != nil { - return template.HTML(""), err - } - return template.HTML(html.String()), nil -} - -var githubProjects = map[string]string{ - "flori/json": "ruby-json", -} - -func main() { - if err := mainWithError(); err != nil { - fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) - os.Exit(1) - } -} - -//go:embed plan.html.tmpl -var embedPlanHTMLTmpl string - -func mainWithError() error { - contribs, err := ReadContribs("contribs.yml") - if err != nil { - return err - } - upstreams, err := ReadUpstreams("upstreams.yml") - if err != nil { - return err - } - tmpl := template.Must(template.New("plan.html"). - Funcs(template.FuncMap{ - "md2html": MarkdownToHTML, - "getUpstream": func(c Contribution) Upstream { - // First try any of the documented upstreams. - for _, cURL := range c.URLs { - for _, upstream := range upstreams { - for _, uURL := range upstream.URLs { - prefix := uURL - if !strings.HasSuffix(prefix, "/") { - prefix += "/" - } - if cURL == uURL || strings.HasPrefix(cURL, prefix) { - return upstream - } - } - } - } - return Upstream{URLs: []string{c.URLs[0]}, Name: "???"} - }, - }). - Parse(embedPlanHTMLTmpl)) - var out bytes.Buffer - if err := tmpl.Execute(&out, contribs); err != nil { - return err - } - if err := os.WriteFile("plan.html", out.Bytes(), 0666); err != nil { - return err - } - return nil -} diff --git a/tags.yml b/tags.yml new file mode 100644 index 0000000..8e0fa2d --- /dev/null +++ b/tags.yml @@ -0,0 +1,27 @@ +docs: + prettyName: Documentation + desc: | + I'm working to improve documentation for GNU/Linux, but more than + that I'm working to improve the forms of documentation that more + skilled technical writers might be afraid or incapable of working + on: `--help` text, generated documentation, and auditing + documentation against the source code to make sure that it is + accurate and complete. +ARM: + prettyName: ARM support + desc: | + Not that folks can't use GNU/Linux on ARM (obviously, the + Raspberry Pi has been a huge success), but there's still a lot + more friction to using GNU/Linux on ARM compared to x86. I'm + working on that. +GI: + prettyName: GObject Introspection + desc: | + GObject Introspection (which is a terrible name for what it is, + btw) is a cross-(language-runtime) object system. GObject was an + object system for C that game out of GTK+, and then GObject + Introspection was created as a way to specify the ABI for working + with an object, so that GObjects could be used from other + languages. I think that GObject Introspection is a really cool + technology that can be the basis of reducing friction between + languages, but it needs better/more-ubiquitous tooling. |