1+ // Copyright (c) 2025 Niema Moshiri and The Zaparoo Project.
2+ // SPDX-License-Identifier: GPL-3.0-or-later
3+ //
4+ // This file is part of go-gameid.
5+ //
6+ // go-gameid is free software: you can redistribute it and/or modify
7+ // it under the terms of the GNU General Public License as published by
8+ // the Free Software Foundation, either version 3 of the License, or
9+ // (at your option) any later version.
10+ //
11+ // go-gameid is distributed in the hope that it will be useful,
12+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ // GNU General Public License for more details.
15+ //
16+ // You should have received a copy of the GNU General Public License
17+ // along with go-gameid. If not, see <https://www.gnu.org/licenses/>.
18+
119// Command gameid identifies video game files and returns metadata.
220package main
321
@@ -22,45 +40,46 @@ var (
2240
2341const appVersion = "0.1.0"
2442
43+ //nolint:gocognit,revive // Main entry point handles all CLI logic
2544func main () {
2645 flag .Usage = func () {
27- fmt .Fprintf (os .Stderr , "Usage: %s -i <file> [options]\n \n " , os . Args [ 0 ] )
28- fmt .Fprintf (os .Stderr , "Identifies video game files and returns metadata.\n \n " )
29- fmt .Fprintf (os .Stderr , "Options:\n " )
46+ _ , _ = fmt .Fprint (os .Stderr , "Usage: " + os . Args [ 0 ] + " -i <file> [options]\n \n " )
47+ _ , _ = fmt .Fprint (os .Stderr , "Identifies video game files and returns metadata.\n \n " )
48+ _ , _ = fmt .Fprint (os .Stderr , "Options:\n " )
3049 flag .PrintDefaults ()
31- fmt .Fprintf (os .Stderr , "\n Examples:\n " )
32- fmt .Fprintf (os .Stderr , " %s -i game.gba\n " , os . Args [ 0 ] )
33- fmt .Fprintf (os .Stderr , " %s -i game.iso -c PSX\n " , os . Args [ 0 ] )
34- fmt .Fprintf (os .Stderr , " %s -i game.n64 -db gamedb.gob.gz -json\n " , os . Args [ 0 ] )
50+ _ , _ = fmt .Fprint (os .Stderr , "\n Examples:\n " )
51+ _ , _ = fmt .Fprint (os .Stderr , " " + os . Args [ 0 ] + " -i game.gba\n " )
52+ _ , _ = fmt .Fprint (os .Stderr , " " + os . Args [ 0 ] + " -i game.iso -c PSX\n " )
53+ _ , _ = fmt .Fprint (os .Stderr , " " + os . Args [ 0 ] + " -i game.n64 -db gamedb.gob.gz -json\n " )
3554 }
3655 flag .Parse ()
3756
3857 if * version {
39- fmt .Printf ("gameid version %s \n " , appVersion )
58+ fmt .Println ("gameid version " + appVersion ) //nolint:revive // Output for CLI
4059 os .Exit (0 )
4160 }
4261
4362 if * listConsoles {
44- fmt .Println ("Supported consoles:" )
63+ fmt .Println ("Supported consoles:" ) //nolint:revive // Output for CLI
4564 for _ , c := range gameid .AllConsoles {
46- fmt .Printf (" %s \n " , c )
65+ fmt .Println (" " + string ( c )) //nolint:revive // Output for CLI
4766 }
4867 os .Exit (0 )
4968 }
5069
5170 if * inputFile == "" {
52- fmt .Fprintf (os .Stderr , "Error: input file required (-i)\n " )
71+ _ , _ = fmt .Fprint (os .Stderr , "Error: input file required (-i)\n " )
5372 flag .Usage ()
5473 os .Exit (1 )
5574 }
5675
5776 // Load database if specified
5877 var db * gameid.GameDatabase
5978 if * dbPath != "" {
60- var err error
61- db , err = gameid .LoadDatabase (* dbPath )
62- if err != nil {
63- fmt .Fprintf (os .Stderr , "Error loading database: %v\n " , err )
79+ var loadErr error
80+ db , loadErr = gameid .LoadDatabase (* dbPath )
81+ if loadErr != nil {
82+ _ , _ = fmt .Fprintf (os .Stderr , "Error loading database: %v\n " , loadErr )
6483 os .Exit (1 )
6584 }
6685 }
@@ -69,58 +88,63 @@ func main() {
6988 var result * gameid.Result
7089 var err error
7190
91+ //nolint:nestif // Console identification requires conditional branching
7292 if * console != "" {
7393 // Console specified, use it directly
74- c , err := gameid .ParseConsole (* console )
75- if err != nil {
76- fmt .Fprintf (os .Stderr , "Error: unknown console '%s'\n " , * console )
77- fmt .Fprintf (os .Stderr , "Use -list-consoles to see supported consoles\n " )
94+ parsedConsole , parseErr := gameid .ParseConsole (* console )
95+ if parseErr != nil {
96+ _ , _ = fmt .Fprintf (os .Stderr , "Error: unknown console '%s'\n " , * console )
97+ _ , _ = fmt .Fprintf (os .Stderr , "Use -list-consoles to see supported consoles\n " )
7898 os .Exit (1 )
7999 }
80- result , err = gameid .IdentifyWithConsole (* inputFile , c , db )
100+ result , err = gameid .IdentifyWithConsole (* inputFile , parsedConsole , db )
81101 if err != nil {
82- fmt .Fprintf (os .Stderr , "Error identifying game: %v\n " , err )
102+ _ , _ = fmt .Fprintf (os .Stderr , "Error identifying game: %v\n " , err )
83103 os .Exit (1 )
84104 }
85105 } else {
86106 // Auto-detect console
87107 result , err = gameid .Identify (* inputFile , db )
88108 if err != nil {
89- fmt .Fprintf (os .Stderr , "Error identifying game: %v\n " , err )
109+ _ , _ = fmt .Fprintf (os .Stderr , "Error identifying game: %v\n " , err )
90110 os .Exit (1 )
91111 }
92112 }
93113
94114 // Output results
95115 if * jsonOutput {
96- outputJSON (result )
116+ if jsonErr := outputJSON (result ); jsonErr != nil {
117+ _ , _ = fmt .Fprintf (os .Stderr , "Error: %v\n " , jsonErr )
118+ os .Exit (1 )
119+ }
97120 } else {
98121 outputText (result )
99122 }
100123}
101124
102- func outputJSON (result * gameid.Result ) {
125+ func outputJSON (result * gameid.Result ) error {
103126 enc := json .NewEncoder (os .Stdout )
104127 enc .SetIndent ("" , " " )
105128 if err := enc .Encode (result ); err != nil {
106- fmt .Fprintf (os .Stderr , "Error encoding JSON: %v\n " , err )
107- os .Exit (1 )
129+ return fmt .Errorf ("encode JSON: %w" , err )
108130 }
131+ return nil
109132}
110133
134+ //nolint:gocognit,revive // Output formatting requires many conditional checks
111135func outputText (result * gameid.Result ) {
112- fmt .Printf ("Console: %s \n " , result .Console )
136+ fmt .Println ("Console: " + string ( result .Console )) //nolint:revive // Output for CLI
113137 if result .ID != "" {
114- fmt .Printf ("ID: %s \n " , result .ID )
138+ fmt .Println ("ID: " + result .ID ) //nolint:revive // Output for CLI
115139 }
116140 if result .Title != "" {
117- fmt .Printf ("Title: %s \n " , result .Title )
141+ fmt .Println ("Title: " + result .Title ) //nolint:revive // Output for CLI
118142 }
119143 if result .InternalTitle != "" && result .InternalTitle != result .Title {
120- fmt .Printf ("Internal Title: %s \n " , result .InternalTitle )
144+ fmt .Println ("Internal Title: " + result .InternalTitle ) //nolint:revive // Output for CLI
121145 }
122146 if result .Region != "" {
123- fmt .Printf ("Region: %s \n " , result .Region )
147+ fmt .Println ("Region: " + result .Region ) //nolint:revive // Output for CLI
124148 }
125149
126150 // Print other metadata (skip those already printed)
@@ -130,19 +154,21 @@ func outputText(result *gameid.Result) {
130154
131155 if len (result .Metadata ) > 0 {
132156 var otherKeys []string
133- for k := range result .Metadata {
134- if ! skipKeys [k ] {
135- otherKeys = append (otherKeys , k )
157+ for key := range result .Metadata {
158+ if ! skipKeys [key ] {
159+ otherKeys = append (otherKeys , key )
136160 }
137161 }
138162
139163 if len (otherKeys ) > 0 {
140- fmt .Println ("\n Metadata:" )
141- for _ , k := range otherKeys {
164+ fmt .Println ("\n Metadata:" ) //nolint:revive // Output for CLI
165+ for _ , key := range otherKeys {
142166 // Format key for display
143- displayKey := strings .ReplaceAll (k , "_" , " " )
167+ displayKey := strings .ReplaceAll (key , "_" , " " )
168+ //nolint:staticcheck // strings.Title is fine for simple ASCII
144169 displayKey = strings .Title (displayKey )
145- fmt .Printf (" %s: %s\n " , displayKey , result .Metadata [k ])
170+ //nolint:revive // Output for CLI
171+ fmt .Println (" " + displayKey + ": " + result .Metadata [key ])
146172 }
147173 }
148174 }
0 commit comments