mirror of
https://github.com/YuzuZensai/Git-Identity-Audit.git
synced 2026-09-13 18:59:04 +00:00
✨ feat: Initial commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/YuzuZensai/Git-Identity-Audit/internal/github"
|
||||
"github.com/YuzuZensai/Git-Identity-Audit/internal/scanner"
|
||||
)
|
||||
|
||||
//go:embed template.html
|
||||
var templateHTML string
|
||||
|
||||
var htmlTemplate = template.Must(template.New("report").Parse(templateHTML))
|
||||
|
||||
func WriteHTML(path string, entries []scanner.Entry, events []github.Event) error {
|
||||
dataJSON, err := json.Marshal(entries)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshaling entries: %w", err)
|
||||
}
|
||||
eventsJSON, err := json.Marshal(events)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshaling events: %w", err)
|
||||
}
|
||||
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating %s: %w", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return htmlTemplate.Execute(f, struct {
|
||||
DataJSON template.JS
|
||||
EventsJSON template.JS
|
||||
GeneratedAt string
|
||||
}{
|
||||
DataJSON: template.JS(dataJSON),
|
||||
EventsJSON: template.JS(eventsJSON),
|
||||
GeneratedAt: time.Now().Format(time.RFC1123),
|
||||
})
|
||||
}
|
||||
|
||||
type summaryRow struct {
|
||||
Name string
|
||||
Email string
|
||||
Count int
|
||||
RepoCounts map[string]int
|
||||
}
|
||||
|
||||
func PrintSummary(entries []scanner.Entry) {
|
||||
rows := map[string]*summaryRow{}
|
||||
for _, e := range entries {
|
||||
key := e.Name + "\x00" + e.Email
|
||||
row, ok := rows[key]
|
||||
if !ok {
|
||||
row = &summaryRow{Name: e.Name, Email: e.Email, RepoCounts: map[string]int{}}
|
||||
rows[key] = row
|
||||
}
|
||||
row.Count++
|
||||
row.RepoCounts[e.Repo]++
|
||||
}
|
||||
|
||||
sorted := make([]*summaryRow, 0, len(rows))
|
||||
for _, r := range rows {
|
||||
sorted = append(sorted, r)
|
||||
}
|
||||
sort.Slice(sorted, func(i, j int) bool { return sorted[i].Count > sorted[j].Count })
|
||||
|
||||
fmt.Printf("\n%d unique identities found:\n\n", len(sorted))
|
||||
for i, r := range sorted {
|
||||
repoNames := make([]string, 0, len(r.RepoCounts))
|
||||
for repo := range r.RepoCounts {
|
||||
repoNames = append(repoNames, repo)
|
||||
}
|
||||
sort.Strings(repoNames)
|
||||
|
||||
fmt.Printf("%3d. %s <%s>\n", i+1, r.Name, r.Email)
|
||||
fmt.Printf(" %d commits across %d repo(s):\n", r.Count, len(repoNames))
|
||||
for _, repo := range repoNames {
|
||||
fmt.Printf(" - %s (%d)\n", repo, r.RepoCounts[repo])
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user