|
1 | 1 | package cmd |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "fmt" |
5 | | - "os" |
6 | | - "os/exec" |
7 | | - "path/filepath" |
8 | | - "strconv" |
9 | | - "strings" |
10 | | - |
| 4 | + "github.com/Norgate-AV/spc/internal/build" |
11 | 5 | "github.com/spf13/cobra" |
12 | | - "github.com/spf13/viper" |
13 | | - |
14 | | - "github.com/Norgate-AV/spc/internal/compiler" |
15 | | - "github.com/Norgate-AV/spc/internal/config" |
16 | 6 | ) |
17 | 7 |
|
18 | 8 | var buildCmd = &cobra.Command{ |
19 | | - Use: "build", |
20 | | - Short: "Build SIMPL+ file(s)", |
21 | | - Long: `Build a SIMPL+ file(s) for the specified target series.`, |
22 | | - RunE: func(cmd *cobra.Command, args []string) error { |
23 | | - return runBuild(cmd, args) |
24 | | - }, |
| 9 | + Use: "build", |
| 10 | + Short: "Build SIMPL+ file(s)", |
| 11 | + Long: `Build a SIMPL+ file(s) for the specified target series.`, |
| 12 | + RunE: runBuild, |
25 | 13 | SilenceUsage: true, |
26 | 14 | } |
27 | 15 |
|
28 | 16 | func runBuild(cmd *cobra.Command, args []string) error { |
29 | | - if len(args) == 0 { |
30 | | - return fmt.Errorf("no files specified") |
31 | | - } |
32 | | - |
33 | | - cfg, err := loadBuildConfig(cmd, args) |
34 | | - if err != nil { |
35 | | - return err |
36 | | - } |
37 | | - |
38 | | - cmdArgs, err := buildCommandArgs(cfg, args) |
39 | | - if err != nil { |
40 | | - return err |
41 | | - } |
42 | | - |
43 | | - series := parseTarget(cfg.Target) |
44 | | - |
45 | | - if cfg.Verbose { |
46 | | - fmt.Printf("Compiler: %s\nTarget: %s\nSeries: %v\nFiles: %v\nOut: %s\nUsersPlusFolders: %v\nCommand: %s %s\n", cfg.CompilerPath, cfg.Target, series, args, cfg.OutputFile, cfg.UserFolders, cfg.CompilerPath, strings.Join(cmdArgs, " ")) |
47 | | - } |
| 17 | + service := build.NewBuildService() |
| 18 | + return service.Build(cmd, args) |
48 | 19 |
|
49 | | - c := execCommand(cfg.CompilerPath, cmdArgs...) |
50 | | - if cmd, ok := c.(*exec.Cmd); ok { |
51 | | - cmd.Stdout = os.Stdout |
52 | | - cmd.Stderr = os.Stderr |
53 | | - } |
54 | | - |
55 | | - err = c.Run() |
56 | | - if err != nil { |
57 | | - if exitErr, ok := err.(*exec.ExitError); ok { |
58 | | - code := exitErr.ExitCode() |
59 | | - if compiler.IsSuccess(code) { |
60 | | - // Crestron compiler success (may have warnings) |
61 | | - return nil |
62 | | - } |
63 | | - |
64 | | - // Print descriptive error message |
65 | | - fmt.Fprintf(os.Stderr, "Compilation failed (exit code %d): %s\n", code, codes.GetErrorMessage(code)) |
66 | | - } |
67 | | - |
68 | | - return err |
69 | | - } |
70 | | - |
71 | | - return nil |
72 | | -} |
73 | | - |
74 | | -func buildCommandArgs(cfg *config.Config, files []string) ([]string, error) { |
75 | | - series := parseTarget(cfg.Target) |
76 | | - if len(series) == 0 { |
77 | | - return nil, fmt.Errorf("invalid target series") |
78 | | - } |
79 | | - |
80 | | - var cmdArgs []string |
81 | | - cmdArgs = append(cmdArgs, "/target") |
82 | | - cmdArgs = append(cmdArgs, series...) |
83 | | - |
84 | | - for _, folder := range cfg.UserFolders { |
85 | | - if folder != "" { |
86 | | - cmdArgs = append(cmdArgs, "/usersplusfolder", folder) |
87 | | - } |
88 | | - } |
89 | | - |
90 | | - cmdArgs = append(cmdArgs, "/rebuild") |
91 | | - |
92 | | - for _, file := range files { |
93 | | - absFile, err := filepath.Abs(file) |
94 | | - if err != nil { |
95 | | - return nil, fmt.Errorf("failed to resolve absolute path for %s: %w", file, err) |
96 | | - } |
97 | | - |
98 | | - cmdArgs = append(cmdArgs, absFile) |
99 | | - } |
100 | | - |
101 | | - if cfg.OutputFile != "" { |
102 | | - cmdArgs = append(cmdArgs, "/out", cfg.OutputFile) |
103 | | - } |
104 | | - |
105 | | - if cfg.Silent { |
106 | | - cmdArgs = append(cmdArgs, "/silent") |
107 | | - } |
108 | | - |
109 | | - return cmdArgs, nil |
110 | | -} |
| 20 | + // Resolve config |
| 21 | + // cfg, err := config.Load() |
| 22 | + // if err != nil { |
| 23 | + // return fmt.Errorf("error loading config: %w", err) |
| 24 | + // } |
111 | 25 |
|
112 | | -func parseTarget(t string) []string { |
113 | | - series := make([]string, 0) |
| 26 | + // fmt.Printf("%+v\n", cfg) |
| 27 | + // fmt.Printf("%+v\n", args) |
114 | 28 |
|
115 | | - for _, r := range t { |
116 | | - if s := int(r - '0'); s >= 2 && s <= 4 { |
117 | | - series = append(series, "series"+strconv.Itoa(s)) |
118 | | - } |
119 | | - } |
120 | | - |
121 | | - return series |
122 | | -} |
123 | | - |
124 | | -func findLocalConfig(dir string) string { |
125 | | - for { |
126 | | - for _, ext := range []string{"yml", "yaml", "json", "toml"} { |
127 | | - path := filepath.Join(dir, ".spc."+ext) |
128 | | - |
129 | | - if _, err := os.Stat(path); err == nil { |
130 | | - return path |
131 | | - } |
132 | | - } |
133 | | - |
134 | | - parent := filepath.Dir(dir) |
135 | | - if parent == dir { |
136 | | - break |
137 | | - } |
138 | | - |
139 | | - dir = parent |
140 | | - } |
141 | | - |
142 | | - return "" |
143 | | -} |
144 | | - |
145 | | -func loadBuildConfig(cmd *cobra.Command, args []string) (*config.Config, error) { |
146 | | - // Set defaults |
147 | | - viper.SetDefault("compiler_path", "C:/Program Files (x86)/Crestron/Simpl/SPlusCC.exe") |
148 | | - viper.SetDefault("target", "234") |
149 | | - viper.SetDefault("silent", false) |
150 | | - viper.SetDefault("verbose", false) |
151 | | - |
152 | | - // global config |
153 | | - appdata := os.Getenv("APPDATA") |
154 | | - if appdata != "" { |
155 | | - globalDir := filepath.Join(appdata, "spc") |
156 | | - |
157 | | - for _, ext := range []string{"yml", "yaml", "json", "toml"} { |
158 | | - globalPath := filepath.Join(globalDir, "config."+ext) |
159 | | - |
160 | | - if _, err := os.Stat(globalPath); err == nil { |
161 | | - viper.SetConfigFile(globalPath) |
162 | | - |
163 | | - if err := viper.ReadInConfig(); err == nil { |
164 | | - break |
165 | | - } |
166 | | - } |
167 | | - } |
168 | | - } |
169 | | - |
170 | | - // local config |
171 | | - if len(args) > 0 { |
172 | | - absFirstFile, err := filepath.Abs(args[0]) |
173 | | - if err != nil { |
174 | | - return nil, fmt.Errorf("failed to resolve absolute path for first file: %w", err) |
175 | | - } |
176 | | - |
177 | | - dir := filepath.Dir(absFirstFile) |
178 | | - localPath := findLocalConfig(dir) |
179 | | - if localPath != "" { |
180 | | - viper.SetConfigFile(localPath) |
181 | | - _ = viper.ReadInConfig() |
182 | | - } |
183 | | - } |
184 | | - |
185 | | - // bind flags |
186 | | - _ = viper.BindPFlag("target", cmd.Flags().Lookup("target")) |
187 | | - _ = viper.BindPFlag("verbose", cmd.Flags().Lookup("verbose")) |
188 | | - _ = viper.BindPFlag("out", cmd.Flags().Lookup("out")) |
189 | | - _ = viper.BindPFlag("usersplusfolder", cmd.Flags().Lookup("usersplusfolder")) |
190 | | - |
191 | | - return config.Load() |
192 | | -} |
193 | | - |
194 | | -var execCommand = func(name string, args ...string) Commander { |
195 | | - return exec.Command(name, args...) |
196 | | -} |
| 29 | + // Validate input |
| 30 | + // if len(args) == 0 { |
| 31 | + // return cmd.Help() |
| 32 | + // } |
197 | 33 |
|
198 | | -type Commander interface { |
199 | | - Run() error |
| 34 | + // return nil |
200 | 35 | } |
0 commit comments