Commit ff213f4
Changed files (7)
pkg/git/git.go
@@ -224,6 +224,9 @@ func Commits(ref Ref, repoDir string) ([]Commit, error) {
"%an", // author name
"%ae", // author email
"%ad", // author date
+ "%cn", // committer name
+ "%ce", // committer email
+ "%cd", // committer date
"%P", // parent hashes
"%D", // ref names without the "(", ")" wrapping.
}
@@ -256,22 +259,31 @@ func Commits(ref Ref, repoDir string) ([]Commit, error) {
if len(parts) != len(format) {
return nil, fmt.Errorf("unexpected commit format: %s", line)
}
- full, short, subject, body, author, email, date, parents, refs :=
- parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7], parts[8]
+ full, short, subject, body, author, email, date :=
+ parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]
+ committerName, committerEmail, committerDate, parents, refs :=
+ parts[7], parts[8], parts[9], parts[10], parts[11]
timestamp, err := strconv.Atoi(date)
if err != nil {
return nil, fmt.Errorf("failed to parse commit date: %w", err)
}
+ committerTimestamp, err := strconv.Atoi(committerDate)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse committer date: %w", err)
+ }
commits = append(commits, Commit{
- Hash: full,
- ShortHash: short,
- Subject: subject,
- Body: body,
- Author: author,
- Email: email,
- Date: time.Unix(int64(timestamp), 0),
- Parents: strings.Fields(parents),
- RefNames: parseRefNames(refs),
+ Hash: full,
+ ShortHash: short,
+ Subject: subject,
+ Body: body,
+ Author: author,
+ Email: email,
+ Date: time.Unix(int64(timestamp), 0),
+ CommitterName: committerName,
+ CommitterEmail: committerEmail,
+ CommitterDate: time.Unix(int64(committerTimestamp), 0),
+ Parents: strings.Fields(parents),
+ RefNames: parseRefNames(refs),
})
}
return commits, nil
pkg/git/types.go
@@ -37,17 +37,20 @@ type Blob struct {
}
type Commit struct {
- Hash string
- ShortHash string
- Subject string
- Body string
- Author string
- Email string
- Date time.Time
- Parents []string
- Branch Ref
- RefNames []RefName
- Href string
+ Hash string
+ ShortHash string
+ Subject string
+ Body string
+ Author string
+ Email string
+ Date time.Time
+ CommitterName string
+ CommitterEmail string
+ CommitterDate time.Time
+ Parents []string
+ Branch Ref
+ RefNames []RefName
+ Href string
}
type RefKind string
branches_json.go
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "encoding/json"
+ "os"
+ "path/filepath"
+
+ "mokhan.ca/antonmedv/gitmal/pkg/git"
+)
+
+type BranchJSON struct {
+ Name string `json:"name"`
+ Commit BranchHead `json:"commit"`
+}
+
+type BranchHead struct {
+ SHA string `json:"sha"`
+}
+
+func generateBranchesJSON(branches []git.Ref, commitsFor map[git.Ref][]git.Commit, params Params) error {
+ list := make([]BranchJSON, 0, len(branches))
+ for _, branch := range branches {
+ commits := commitsFor[branch]
+ var sha string
+ if len(commits) > 0 {
+ sha = commits[0].Hash
+ }
+ list = append(list, BranchJSON{
+ Name: branch.String(),
+ Commit: BranchHead{SHA: sha},
+ })
+ }
+
+ outPath := filepath.Join(params.OutputDir, "branches.json")
+ f, err := os.Create(outPath)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ encoder := json.NewEncoder(f)
+ encoder.SetIndent("", " ")
+ return encoder.Encode(list)
+}
commits_atom.go
@@ -0,0 +1,96 @@
+package main
+
+import (
+ "encoding/xml"
+ "os"
+ "path/filepath"
+
+ "mokhan.ca/antonmedv/gitmal/pkg/git"
+)
+
+type AtomFeed struct {
+ XMLName xml.Name `xml:"feed"`
+ XMLNS string `xml:"xmlns,attr"`
+ ID string `xml:"id"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ Link []AtomLink `xml:"link"`
+ Entries []AtomEntry `xml:"entry"`
+}
+
+type AtomLink struct {
+ Rel string `xml:"rel,attr"`
+ Type string `xml:"type,attr"`
+ Href string `xml:"href,attr"`
+}
+
+type AtomEntry struct {
+ ID string `xml:"id"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ Author AtomAuthor `xml:"author"`
+ Content string `xml:"content"`
+ Link AtomLink `xml:"link"`
+}
+
+type AtomAuthor struct {
+ Name string `xml:"name"`
+ Email string `xml:"email,omitempty"`
+}
+
+func generateCommitsAtom(commits []git.Commit, params Params) error {
+ outDir := filepath.Join(params.OutputDir, "commits")
+ if err := os.MkdirAll(outDir, 0o755); err != nil {
+ return err
+ }
+
+ var updated string
+ if len(commits) > 0 {
+ updated = commits[0].Date.Format("2006-01-02T15:04:05Z")
+ }
+
+ entries := make([]AtomEntry, len(commits))
+ for i, c := range commits {
+ content := c.Subject
+ if c.Body != "" {
+ content = c.Subject + "\n\n" + c.Body
+ }
+ entries[i] = AtomEntry{
+ ID: "urn:sha:" + c.Hash,
+ Title: c.Subject,
+ Updated: c.Date.Format("2006-01-02T15:04:05Z"),
+ Author: AtomAuthor{Name: c.Author, Email: c.Email},
+ Content: content,
+ Link: AtomLink{
+ Rel: "alternate",
+ Type: "text/html",
+ Href: "commit/" + c.Hash + ".html",
+ },
+ }
+ }
+
+ feed := AtomFeed{
+ XMLNS: "http://www.w3.org/2005/Atom",
+ ID: "urn:gitmal:" + params.Name + ":" + params.Ref.String(),
+ Title: params.Name + " commits on " + params.Ref.String(),
+ Updated: updated,
+ Link: []AtomLink{
+ {Rel: "self", Type: "application/atom+xml", Href: "commits/" + params.Ref.DirName() + ".atom"},
+ },
+ Entries: entries,
+ }
+
+ outPath := filepath.Join(outDir, params.Ref.DirName()+".atom")
+ f, err := os.Create(outPath)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ if _, err := f.WriteString(xml.Header); err != nil {
+ return err
+ }
+ encoder := xml.NewEncoder(f)
+ encoder.Indent("", " ")
+ return encoder.Encode(feed)
+}
commits_json.go
@@ -0,0 +1,71 @@
+package main
+
+import (
+ "encoding/json"
+ "os"
+ "path/filepath"
+
+ "mokhan.ca/antonmedv/gitmal/pkg/git"
+)
+
+type CommitJSON struct {
+ SHA string `json:"sha"`
+ Commit CommitDetail `json:"commit"`
+ Parents []ParentRef `json:"parents"`
+}
+
+type CommitDetail struct {
+ Author PersonInfo `json:"author"`
+ Committer PersonInfo `json:"committer"`
+ Message string `json:"message"`
+}
+
+type PersonInfo struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ Date string `json:"date"`
+}
+
+type ParentRef struct {
+ SHA string `json:"sha"`
+}
+
+func toCommitJSON(c git.Commit) CommitJSON {
+ message := c.Subject
+ if c.Body != "" {
+ message = c.Subject + "\n\n" + c.Body
+ }
+ parents := make([]ParentRef, len(c.Parents))
+ for i, p := range c.Parents {
+ parents[i] = ParentRef{SHA: p}
+ }
+ return CommitJSON{
+ SHA: c.Hash,
+ Commit: CommitDetail{
+ Author: PersonInfo{Name: c.Author, Email: c.Email, Date: c.Date.Format("2006-01-02T15:04:05Z")},
+ Committer: PersonInfo{Name: c.CommitterName, Email: c.CommitterEmail, Date: c.CommitterDate.Format("2006-01-02T15:04:05Z")},
+ Message: message,
+ },
+ Parents: parents,
+ }
+}
+
+func generateCommitsJSON(commits []git.Commit, params Params) error {
+ outDir := filepath.Join(params.OutputDir, "commits")
+ if err := os.MkdirAll(outDir, 0o755); err != nil {
+ return err
+ }
+ list := make([]CommitJSON, len(commits))
+ for i, c := range commits {
+ list[i] = toCommitJSON(c)
+ }
+ outPath := filepath.Join(outDir, params.Ref.DirName()+".json")
+ f, err := os.Create(outPath)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ encoder := json.NewEncoder(f)
+ encoder.SetIndent("", " ")
+ return encoder.Encode(list)
+}
main.go
@@ -194,6 +194,10 @@ func main() {
panic(err)
}
+ if err := generateBranchesJSON(branches, commitsFor, params); err != nil {
+ panic(err)
+ }
+
var defaultBranchFiles []git.Blob
for i, branch := range branches {
@@ -226,6 +230,14 @@ func main() {
if err != nil {
panic(err)
}
+
+ if err := generateCommitsJSON(commitsFor[branch], params); err != nil {
+ panic(err)
+ }
+
+ if err := generateCommitsAtom(commitsFor[branch], params); err != nil {
+ panic(err)
+ }
}
}
@@ -244,6 +256,14 @@ func main() {
panic(err)
}
+ if err := generateTagsAtom(tags, params); err != nil {
+ panic(err)
+ }
+
+ if err := generateReleasesAtom(tags, params); err != nil {
+ panic(err)
+ }
+
// Index page generation
if !noFiles {
if len(defaultBranchFiles) == 0 {