1+ package main
2+
3+ import (
4+ "fmt"
5+ "os"
6+ "runtime"
7+ "time"
8+
9+ "github.com/loSpaccaBit/git-stats-cli/internal/analyzer"
10+ "github.com/loSpaccaBit/git-stats-cli/internal/formatter"
11+ "github.com/loSpaccaBit/git-stats-cli/internal/report"
12+ "github.com/loSpaccaBit/git-stats-cli/internal/version"
13+ "github.com/spf13/cobra"
14+ )
15+
16+ var (
17+ noColor bool
18+ topAuthors int
19+ churn bool
20+ noChurn bool
21+ months int
22+ workers int
23+ verbose bool
24+ )
25+
26+ func main () {
27+ if err := newRootCmd ().Execute (); err != nil {
28+ fmt .Fprintln (os .Stderr , err )
29+ os .Exit (1 )
30+ }
31+ }
32+
33+ func newRootCmd () * cobra.Command {
34+ root := & cobra.Command {
35+ Use : "git-stats" ,
36+ Short : "Analyze Git repositories and generate insightful reports" ,
37+ Long : `git-stats reads repository history with go-git and produces production-grade statistics.
38+
39+ Performance:
40+ By default churn (line diff stats) is OFF for fast analysis on large repos.
41+ Use --churn to enable it. Parallel workers are used automatically.
42+
43+ Features:
44+ - All locally available commits (every branch/tag object in the repo)
45+ - GitHub Linguist language detection via go-enry
46+ - Author rankings, activity windows, monthly trends, and optional code churn
47+ - JSON, Markdown, and HTML export` ,
48+ Version : version .Version ,
49+ }
50+
51+ root .PersistentFlags ().BoolVar (& noColor , "no-color" , false , "disable colored terminal output" )
52+ root .PersistentFlags ().IntVar (& topAuthors , "top" , 10 , "number of top authors to display" )
53+ root .PersistentFlags ().BoolVar (& churn , "churn" , false , "compute line churn stats (slower on large repos)" )
54+ root .PersistentFlags ().BoolVar (& noChurn , "no-churn" , false , "skip line churn (deprecated: churn is off by default)" )
55+ root .PersistentFlags ().IntVar (& months , "months" , 12 , "number of monthly activity buckets to include" )
56+ root .PersistentFlags ().IntVar (& workers , "workers" , runtime .GOMAXPROCS (0 ), "parallel workers for churn analysis" )
57+ root .PersistentFlags ().BoolVarP (& verbose , "verbose" , "v" , false , "print analysis duration to stderr" )
58+
59+ root .AddCommand (newAnalyzeCmd ())
60+ root .AddCommand (newReportCmd ())
61+
62+ return root
63+ }
64+
65+ func analysisOptions () analyzer.Options {
66+ opts := analyzer .DefaultOptions ()
67+ opts .TopAuthors = topAuthors
68+ opts .MonthlyBuckets = months
69+ opts .IncludeChurn = churn && ! noChurn
70+ opts .Workers = workers
71+ return opts
72+ }
73+
74+ func newAnalyzeCmd () * cobra.Command {
75+ return & cobra.Command {
76+ Use : "analyze [path]" ,
77+ Short : "Analyze a local Git repository" ,
78+ Args : cobra .MaximumNArgs (1 ),
79+ RunE : func (cmd * cobra.Command , args []string ) error {
80+ path := "."
81+ if len (args ) > 0 {
82+ path = args [0 ]
83+ }
84+
85+ start := time .Now ()
86+ data , err := analyzer .AnalyzeWithOptions (path , analysisOptions ())
87+ if err != nil {
88+ return err
89+ }
90+ if verbose {
91+ fmt .Fprintf (os .Stderr , "analysis completed in %s\n " , time .Since (start ).Round (time .Millisecond ))
92+ }
93+ return formatter .PrintTerminal (data , noColor )
94+ },
95+ }
96+ }
97+
98+ func newReportCmd () * cobra.Command {
99+ var format string
100+ var output string
101+
102+ cmd := & cobra.Command {
103+ Use : "report [path]" ,
104+ Short : "Generate a JSON, Markdown, or HTML report" ,
105+ Args : cobra .MaximumNArgs (1 ),
106+ RunE : func (cmd * cobra.Command , args []string ) error {
107+ path := "."
108+ if len (args ) > 0 {
109+ path = args [0 ]
110+ }
111+
112+ parsed , err := report .ParseFormat (format )
113+ if err != nil {
114+ return err
115+ }
116+
117+ start := time .Now ()
118+ data , err := analyzer .AnalyzeWithOptions (path , analysisOptions ())
119+ if err != nil {
120+ return err
121+ }
122+ if verbose {
123+ fmt .Fprintf (os .Stderr , "analysis completed in %s\n " , time .Since (start ).Round (time .Millisecond ))
124+ }
125+
126+ if output != "" && output != "-" {
127+ if writeErr := report .WriteOutput (output , parsed , data ); writeErr != nil {
128+ return writeErr
129+ }
130+ fmt .Fprintf (os .Stderr , "Report written to %s (%s)\n " , output , formatter .FormatSummary (data ))
131+ return nil
132+ }
133+
134+ return report .PrintOutput (parsed , data )
135+ },
136+ }
137+
138+ cmd .Flags ().StringVarP (& format , "format" , "f" , "json" , "output format: json, md, html" )
139+ cmd .Flags ().StringVarP (& output , "output" , "o" , "" , "output file path (stdout if empty or '-')" )
140+
141+ return cmd
142+ }
0 commit comments