4 files changed,
71 insertions(+),
44 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-03-19 16:49:25 +0200
Authored at:
2026-03-18 12:44:13 +0200
Change ID:
zkmylrsvmzrzqwvvqzmsonspqslukkxo
Parent:
b598730
jump to
| M | flake.nix |
| M | go.mod |
| M | go.sum |
| M | internal/handlers/feed.go |
M
flake.nix
路路路 15 15 pname = "mugit"; 16 16 version = version; 17 17 src = ./.; 18 - vendorHash = "sha256-LQE7pyxzUHJpTN51HjiamGYg25MX72I/jSPzmjKfTtI="; 18 + vendorHash = "sha256-rnBcUcEN24Qul0Fljo7aQ9aholXDZuUgQhoyzhEC49E="; 19 19 ldflags = [ "-s" "-w" "-X main.version=${version}" ]; 20 20 meta = with pkgs.lib; { 21 21 homepage = "https://git.olexsmir.xyz/mugit";
M
go.sum
路路路 36 36 github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= 37 37 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 38 38 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 39 -github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= 40 -github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= 41 39 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 42 40 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 43 41 github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY=
M
internal/handlers/feed.go
路路路 1 1 package handlers 2 2 3 3 import ( 4 + "encoding/xml" 4 5 "net/http" 5 6 "net/url" 6 - 7 - "github.com/gorilla/feeds" 7 + "time" 8 8 ) 9 9 10 +type rssFeedXML struct { 11 + XMLName xml.Name `xml:"rss"` 12 + Version string `xml:"version,attr"` 13 + Channel rssChannelXML `xml:"channel"` 14 +} 15 + 16 +type rssChannelXML struct { 17 + Title string `xml:"title"` 18 + Link string `xml:"link"` 19 + Description string `xml:"description"` 20 + Items []rssItemXML `xml:"item"` 21 +} 22 + 23 +type rssItemXML struct { 24 + Title string `xml:"title"` 25 + Link string `xml:"link"` 26 + Guid string `xml:"guid"` 27 + Description string `xml:"description,omitempty"` 28 + PubDate string `xml:"pubDate,omitempty"` 29 +} 30 + 10 31 func (h *handlers) repoFeedHandler(w http.ResponseWriter, r *http.Request) { 11 32 repo, err := h.openPublicRepo(r.PathValue("name"), "") 12 33 if err != nil { 路路路 21 42 } 22 43 23 44 repoName := repo.Name() 24 - 25 45 feedLink, err := url.JoinPath("http://", h.c.Meta.Host, repoName) 26 46 if err != nil { 27 47 h.write500(w, err) 28 48 return 29 49 } 30 50 31 - feed := &feeds.Feed{ 32 - Title: repoName, 33 - Link: &feeds.Link{Href: feedLink}, 34 - Description: desc, 51 + feed := rssFeedXML{ 52 + Version: "2.0", 53 + Channel: rssChannelXML{ 54 + Title: repoName, 55 + Link: feedLink, 56 + Description: desc, 57 + }, 35 58 } 36 59 37 60 // branches 路路路 43 66 44 67 for _, branch := range branches { 45 68 href, _ := url.JoinPath("http://", h.c.Meta.Host, repoName, "tree", branch.Name) 46 - feed.Items = append(feed.Items, &feeds.Item{ 47 - Id: "b:" + branch.Name, 48 - Title: "branch: " + branch.Name, 49 - Link: &feeds.Link{Href: href}, 50 - Updated: branch.LastUpdate, 51 - }) 69 + it := rssItemXML{ 70 + Title: "branch: " + branch.Name, 71 + Link: href, 72 + Guid: href, 73 + } 74 + if !branch.LastUpdate.IsZero() { 75 + it.PubDate = branch.LastUpdate.Format(time.RFC1123Z) 76 + } 77 + feed.Channel.Items = append(feed.Channel.Items, it) 52 78 } 53 79 54 80 // tags 路路路 59 85 60 86 for _, tag := range tags { 61 87 href, _ := url.JoinPath("http://", h.c.Meta.Host, repoName, "tree", tag.Name()) 62 - feed.Items = append(feed.Items, &feeds.Item{ 63 - Id: "t:" + tag.Name(), 64 - Title: "tag: " + tag.Name(), 65 - Link: &feeds.Link{Href: href}, 66 - Updated: tag.When(), 67 - Content: tag.Message(), 68 - }) 88 + it := rssItemXML{ 89 + Title: "tag: " + tag.Name(), 90 + Link: href, 91 + Guid: href, 92 + Description: tag.Message(), 93 + } 94 + if !tag.When().IsZero() { 95 + it.PubDate = tag.When().Format(time.RFC1123Z) 96 + } 97 + feed.Channel.Items = append(feed.Channel.Items, it) 69 98 } 70 99 71 - rss, err := feed.ToRss() 72 - if err != nil { 100 + w.Header().Set("Content-Type", "application/rss+xml") 101 + w.Write([]byte(xml.Header)) 102 + if err := xml.NewEncoder(w).Encode(feed); err != nil { 73 103 h.write500(w, err) 74 104 return 75 105 } 76 - 77 - w.Header().Set("Content-Type", "application/rss+xml") 78 - w.Write([]byte(rss)) 79 106 } 80 107 81 108 func (h *handlers) indexFeedHandler(w http.ResponseWriter, r *http.Request) { 路路路 91 118 return 92 119 } 93 120 94 - feed := &feeds.Feed{ 95 - Title: h.c.Meta.Host, 96 - Link: &feeds.Link{Href: feedLink}, 97 - Description: h.c.Meta.Description, 121 + feed := rssFeedXML{ 122 + Version: "2.0", 123 + Channel: rssChannelXML{ 124 + Title: h.c.Meta.Host, 125 + Link: feedLink, 126 + Description: h.c.Meta.Description, 127 + }, 98 128 } 99 129 100 130 for _, repo := range repos { 101 131 href, _ := url.JoinPath("http://", h.c.Meta.Host, repo.Name) 102 - feed.Items = append(feed.Items, &feeds.Item{ 132 + it := rssItemXML{ 103 133 Title: repo.Name, 104 - Link: &feeds.Link{Href: href}, 134 + Link: href, 135 + Guid: href, 105 136 Description: repo.Desc, 106 - Id: repo.Name, 107 - Updated: repo.LastCommit, 108 - Content: repo.Desc, 109 - }) 137 + } 138 + if !repo.LastCommit.IsZero() { 139 + it.PubDate = repo.LastCommit.Format(time.RFC1123Z) 140 + } 141 + feed.Channel.Items = append(feed.Channel.Items, it) 110 142 } 111 143 112 - rss, err := feed.ToRss() 113 - if err != nil { 144 + w.Header().Set("Content-Type", "application/rss+xml") 145 + w.Write([]byte(xml.Header)) 146 + if err := xml.NewEncoder(w).Encode(feed); err != nil { 114 147 h.write500(w, err) 115 148 return 116 149 } 117 - 118 - w.Header().Set("Content-Type", "application/rss+xml") 119 - w.Write([]byte(rss)) 120 150 }