• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dikaeinstein / godl / 25742345227

12 May 2026 02:50PM UTC coverage: 48.537%. First build
25742345227

Pull #2

github

dikaeinstein
use go-dl for downloading and installing go binaries

- updated ci-cd workflow to use latest versions of actions and macos-15 runner
- updated install sub command to use symlinks
Pull Request #2: use go-dl for downloading and installing go binaries

49 of 134 new or added lines in 15 files covered. (36.57%)

564 of 1162 relevant lines covered (48.54%)

1.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

38.64
/internal/cli/cli.go
1
package cli
2

3
import (
4
        "context"
5
        "errors"
6
        "net/http"
7
        "path/filepath"
8

9
        "github.com/MakeNowJust/heredoc"
10
        "github.com/mitchellh/go-homedir"
11
        "github.com/spf13/cobra"
12
        "github.com/spf13/viper"
13

14
        "github.com/dikaeinstein/downloader/pkg/hash"
15

16
        "github.com/dikaeinstein/godl/internal/app"
17
        "github.com/dikaeinstein/godl/internal/archives"
18
        "github.com/dikaeinstein/godl/internal/downloader"
19
        "github.com/dikaeinstein/godl/internal/godlutil"
20
        "github.com/dikaeinstein/godl/pkg/exitcode"
21
        "github.com/dikaeinstein/godl/pkg/fsys"
22
        "github.com/dikaeinstein/godl/pkg/text"
23
)
24

25
func newRootCmd() *cobra.Command {
16✔
26
        rootCmd := &cobra.Command{
16✔
27
                Use:          "godl [command]",
16✔
28
                Short:        "Godl is a CLI tool used to download and install go binary releases on mac.",
16✔
29
                SilenceUsage: true,
16✔
30
                PreRunE:      setupConfig,
16✔
31
        }
16✔
32
        rootCmd.SetUsageTemplate(usageTemplate())
16✔
33

16✔
34
        setupFlags(rootCmd)
16✔
35

16✔
36
        return rootCmd
16✔
37
}
16✔
38

39
func setupFlags(cmd *cobra.Command) {
16✔
40
        cmd.PersistentFlags().
16✔
41
                Bool("debug", false, "Used to turn on debug mode.")
16✔
42
        cmd.PersistentFlags().
16✔
43
                String("config-file", "", "config file (default is $HOME/.godl/config)")
16✔
44
}
16✔
45

46
func registerSubCommands(root *cobra.Command, subCmds []*cobra.Command) {
15✔
47
        for _, subCmd := range subCmds {
30✔
48
                root.AddCommand(subCmd)
15✔
49
        }
15✔
50
}
51

52
func setupConfig(cmd *cobra.Command, args []string) error {
×
53
        if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
×
54
                return err
×
55
        }
×
56

57
        cfgFile := viper.GetString("config-file")
×
58

×
59
        if cfgFile != "" {
×
60
                // use config file from the flag
×
61
                viper.SetConfigFile(cfgFile)
×
62
        } else {
×
63
                // use default config file path
×
64
                home, err := homedir.Dir()
×
65
                if err != nil {
×
66
                        return err
×
67
                }
×
68

69
                defaultCfgFile := filepath.Join(home, ".godl", "config.json")
×
70
                viper.SetConfigFile(defaultCfgFile)
×
71
        }
72

73
        if err := viper.ReadInConfig(); err != nil {
×
74
                // it's ok if config file doesn't exist
×
75
                e := &viper.ConfigFileNotFoundError{}
×
76
                if !errors.As(err, e) {
×
77
                        return err
×
78
                }
×
79
        }
80

81
        viper.SetEnvPrefix("godl")
×
82
        viper.AutomaticEnv()
×
83

×
84
        return nil
×
85
}
86

87
func usageTemplate() string {
16✔
88
        return heredoc.Docf(`%s:{{if .Runnable}}
16✔
89
  {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
16✔
90
  {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
16✔
91

16✔
92
%s:
16✔
93
  {{.NameAndAliases}}{{end}}{{if .HasExample}}
16✔
94

16✔
95
%s:
16✔
96
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
16✔
97

16✔
98
%s:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
16✔
99
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
16✔
100

16✔
101
%s:
16✔
102
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
16✔
103

16✔
104
%s:
16✔
105
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
16✔
106

16✔
107
%s:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
16✔
108
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
16✔
109

16✔
110
Use "{{.CommandPath}} help [command]" or "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
16✔
111
`, text.Bold("USAGE"), text.Bold("ALIASES"), text.Bold("EXAMPLES"),
16✔
112
                text.Bold("AVAILABLE COMMANDS"), text.Bold("FLAGS"),
16✔
113
                text.Bold("INHERITED FLAGS"), text.Bold("ADDITIONAL HELP TOPICS"))
16✔
114
}
16✔
115

116
const distURL = "https://storage.googleapis.com/golang/"
117

118
func Run(info app.BuildInfo) int {
×
119
        godl := newRootCmd()
×
120

×
121
        // subcommands
×
122
        completionCmd := newCompletionCmd()
×
123
        downloadCmd := newDownloadCmd(http.DefaultClient)
×
124
        installCmd, err := setupInstallCmd()
×
125
        if err != nil {
×
126
                return exitcode.Get(err)
×
127
        }
×
128

129
        lsCmd := newListCmd()
×
130
        lsRemoteCmd := newListRemoteCmd(http.DefaultClient)
×
131
        updateCmd := newUpdateCmd(http.DefaultClient, info)
×
132
        versionCmd := newVersionCmd(info)
×
133

×
134
        registerSubCommands(godl, []*cobra.Command{
×
135
                completionCmd,
×
136
                downloadCmd,
×
137
                installCmd,
×
138
                lsRemoteCmd,
×
139
                lsCmd,
×
140
                updateCmd,
×
141
                versionCmd,
×
142
        })
×
143

×
144
        if execErr := godl.ExecuteContext(context.Background()); execErr != nil {
×
145
                return exitcode.Get(execErr)
×
146
        }
×
147

148
        return 0
×
149
}
150

151
func setupInstallCmd() (*cobra.Command, error) {
×
152
        dlDir, err := godlutil.GetDownloadDir()
×
153
        if err != nil {
×
154
                return nil, err
×
155
        }
×
156

157
        dl, err := downloader.New(
×
158
                fsys.OsFS{},
×
159
                hash.NewRemoteHasher(http.DefaultClient),
×
160
                hash.Verifier{},
×
161
                http.DefaultClient,
×
162
                distURL,
×
163
                dlDir,
×
164
                false,
×
165
        )
×
166
        if err != nil {
×
167
                return nil, err
×
168
        }
×
169

170
        installer := app.Install{
×
NEW
171
                Archiver:    archives.NewTarGZ(),
×
NEW
172
                Dl:          dl,
×
NEW
173
                DownloadDir: dlDir,
×
NEW
174
                FS:          fsys.OsFS{},
×
175
        }
×
176

×
177
        return newInstallCmd(http.DefaultClient, dl, &installer), nil
×
178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc