@@ -14,7 +14,10 @@ import (
1414 "text/template"
1515)
1616
17- // geanyData contains the data that geany provies on itself.
17+ // ErrWriterNil indicates that the provided io.Writer is nil and cannot be used.
18+ var ErrWriterNil = errors .New ("writer is nil" )
19+
20+ // geanyData contains the data that geany provides on itself.
1821type geanyData struct {
1922 VcsRevision string
2023 VcsTime string
@@ -24,12 +27,15 @@ type geanyData struct {
2427
2528// logoData is the structure given as data to the templating engine.
2629// It contains the geany provided build information and the user provided data.
30+ // The user is not required to pass data, in that case nil should be passed. In any case,
31+ // the data accessed in the logo template and provided data must match.
2732type logoData struct {
28- Geany geanyData
29- Values any
33+ Geany geanyData // build information
34+ Values any // user provided data
3035}
3136
32- // getBuildInfo is a global variable to mock it easily in tests.
37+ // getBuildInfo is a global variable to mock it easily in tests. Take into account that
38+ // this variable can produce race conditions in parallel testing.
3339var getBuildInfo = debug .ReadBuildInfo //nolint:gochecknoglobals
3440
3541// prepareLogoData collects the build information and the user-provided data
@@ -45,7 +51,7 @@ func prepareLogoData(values any) logoData {
4551 Values : values ,
4652 }
4753
48- if buildInfo , ok := getBuildInfo (); ok {
54+ if buildInfo , ok := getBuildInfo (); ok && buildInfo != nil {
4955 result .Geany .GoVersion = buildInfo .GoVersion
5056
5157 for _ , s := range buildInfo .Settings {
@@ -68,25 +74,29 @@ func prepareLogoData(values any) logoData {
6874// PrintSimpleWriter outputs just the name of the program, the build information
6975// and, in case, the user given data to a user provided io.Writer.
7076func PrintSimpleWriter (writer io.Writer , values any ) error {
77+ if writer == nil {
78+ return ErrWriterNil
79+ }
80+
7181 revData := prepareLogoData (values )
7282
7383 // normally we have the program's name given as the first argument
74- if len (os .Args ) > 0 {
75- fmt .Printf ("%s\n " , os .Args [0 ])
84+ if len (os .Args ) > 0 && os .Args [0 ] != "" {
85+ if _ , err := fmt .Fprintf (writer , "%s\n " , os .Args [0 ]); err != nil {
86+ return fmt .Errorf ("could not write program name: %w" , err )
87+ }
7688 }
7789
7890 encoder := json .NewEncoder (writer )
7991 encoder .SetIndent ("" , " " )
8092
8193 // we suppress the linter here, as we cannot guarantee for users data.
82- err := encoder .Encode (revData ) //nolint:musttag
83-
84- if err == nil {
85- _ , err = fmt .Fprintln (writer )
94+ if err := encoder .Encode (revData ); err != nil { //nolint:musttag
95+ return fmt .Errorf ("could not encode user data: %w" , err )
8696 }
8797
88- if err != nil {
89- return fmt .Errorf ("could not write: %w" , err )
98+ if _ , err := fmt . Fprintln ( writer ); err != nil {
99+ return fmt .Errorf ("could not write final newline : %w" , err )
90100 }
91101
92102 return nil
@@ -105,23 +115,32 @@ func PrintSimple(values any) error {
105115// - VcsModified
106116// - GoVersion
107117//
108- // these can be referenced in the template, e.g., using {{ .VcsRevision }}.
118+ // these can be referenced in the template, e.g., using ` {{ .Geany. VcsRevision }}` .
109119// An additional custom value can be accessed via the Values field. Its type must match the way
110- // that it is accessed in the logo.
120+ // that it is accessed in the logo and is accessed using e.g. `{{ .Values.Foo }}`.
121+ //
122+ // The template is parsed and executed. In case of an error, the program's name and user given
123+ // data are printed as JSON as fallback. The original error and, in case, the error of the fallback
124+ // are returned.
111125func PrintLogoWriter (writer io.Writer , tmpl string , values any ) error {
126+ if writer == nil {
127+ return ErrWriterNil
128+ }
129+
112130 revData := prepareLogoData (values )
113131
114132 logo := template .New ("logo" )
115- template .Must (logo .Parse (tmpl ))
133+
134+ if _ , err := logo .Parse (tmpl ); err != nil {
135+ return fmt .Errorf ("could not parse template: %w" , err )
136+ }
116137
117138 if err := logo .Execute (writer , revData ); err != nil {
118139 return errors .Join (err , PrintSimpleWriter (writer , values ))
119140 }
120141
121- _ , err := fmt .Fprintln (writer )
122-
123- if err != nil {
124- return fmt .Errorf ("could not write: %w" , err )
142+ if _ , err := fmt .Fprintln (writer ); err != nil {
143+ return fmt .Errorf ("could not write final newline: %w" , err )
125144 }
126145
127146 return nil
0 commit comments