/
config.go
153 lines (129 loc) · 3.82 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) 2020-2021 C4 Project
//
// This file is part of c4t.
// Licenced under the MIT licence; see `LICENSE`.
// Package config implements the c4f-config app.
package config
import (
"context"
"fmt"
"io"
"github.com/c4-project/c4t/internal/config/pretty"
"github.com/mitchellh/go-wordwrap"
"github.com/c4-project/c4t/internal/helper/srvrun"
"github.com/c4-project/c4t/internal/config"
"github.com/c4-project/c4t/internal/ux/stdflag"
c "github.com/urfave/cli/v2"
)
const (
// Name is the name of the config binary.
Name = "c4t-config"
usage = "manipulates config"
readme = `
This program provides utilities for manipulating the c4t config file.
With no arguments, it produces an initial config file for the current system and dumps it to stdout.
The following flags print information about the current c4t config:
-` + FlagPrintGlobalPath + `: prints the path that c4t uses by default when looking for a config file.
You can use this to open the global config in a text editor, or save the config file produced by this program there.
-` + FlagPrintCompilers + `: prints a list of the currently-configured compilers.`
// FlagPrintGlobalPath is the flag used for printing the global path.
FlagPrintGlobalPath = "print-global-path"
flagPrintGlobalPathShort = "G"
usagePrintPath = "print path to global config file, rather than generating a new one"
FlagPrintCompilers = "print-compilers"
flagPrintCompilersShort = "c"
usagePrintCompilers = "print information about configured compilers"
)
// App is the entry point for c4t-config.
func App(outw, errw io.Writer) *c.App {
a := &c.App{
Name: Name,
Usage: usage,
Description: wordwrap.WrapString(readme, 80),
Flags: flags(),
Action: func(ctx *c.Context) error {
return run(ctx, outw, errw)
},
}
return stdflag.SetCommonAppSettings(a, outw, errw)
}
func flags() []c.Flag {
flags := []c.Flag{
&c.BoolFlag{
Name: FlagPrintGlobalPath,
Aliases: []string{flagPrintGlobalPathShort},
Usage: usagePrintPath,
},
&c.BoolFlag{
Name: FlagPrintCompilers,
Aliases: []string{flagPrintCompilersShort},
Usage: usagePrintCompilers,
},
}
flags = append(flags, stdflag.TabulatorCliFlags()...)
flags = append(flags, stdflag.ConfFileCliFlag())
return flags
}
func run(ctx *c.Context, outw io.Writer, errw io.Writer) error {
if dc := dumpConfigFromCli(ctx); dc.isDumping() {
return dump(ctx, outw, dc)
}
return probeAndDump(ctx.Context, outw, errw)
}
func dump(ctx *c.Context, outw io.Writer, dc *dumpConfig) error {
var (
// Loaded only if we need it for dumping.
cfg *config.Config
err error
)
if dc.needsConfig() {
if cfg, err = stdflag.ConfigFromCli(ctx); err != nil {
return err
}
}
if dc.globalPath {
if err = printGlobalPath(outw); err != nil {
return err
}
}
if dc.compilers {
t := stdflag.TabulatorFromCli(ctx, outw)
if err = pretty.TabulateCompilers(t, cfg); err != nil {
return err
}
}
return err
}
type dumpConfig struct {
globalPath bool
compilers bool
}
func dumpConfigFromCli(ctx *c.Context) *dumpConfig {
return &dumpConfig{
globalPath: ctx.Bool(FlagPrintGlobalPath),
compilers: ctx.Bool(FlagPrintCompilers),
}
}
func (d dumpConfig) isDumping() bool {
// to be expanded if we add more config dumpers
return d.compilers || d.globalPath
}
func (d dumpConfig) needsConfig() bool {
// to be expanded if we add more config dumpers
return d.compilers
}
func printGlobalPath(outw io.Writer) error {
path, err := config.GlobalFile()
if err != nil {
return err
}
_, err = fmt.Fprintln(outw, path)
return err
}
func probeAndDump(ctx context.Context, outw io.Writer, errw io.Writer) error {
cfg := config.Config{}
if err := config.LocalProberSet().Probe(ctx, srvrun.NewExecRunner(srvrun.StderrTo(errw)), &cfg); err != nil {
return err
}
return cfg.Dump(outw)
}