Skip to content

Commit 9b4b124

Browse files
committed
WIP
1 parent d532850 commit 9b4b124

File tree

11 files changed

+224
-276
lines changed

11 files changed

+224
-276
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ COVERAGE=coverage.out
55

66
MCLI_SOURCE_FILES?=./cmd/mongocli
77
MCLI_BINARY_NAME=mongocli
8-
MCLI_VERSION?=$(shell git tag --list 'mongocli/v*' --sort=committerdate | tail -1 | cut -d "v" -f 2 | xargs -I % sh -c 'echo %-next' )
8+
MCLI_VERSION?=1.21.0 #$(shell git tag --list 'mongocli/v*' --sort=committerdate | tail -1 | cut -d "v" -f 2 | xargs -I % sh -c 'echo %-next' )
99
MCLI_GIT_SHA?=$(shell git rev-parse HEAD)
1010
MCLI_DESTINATION=./bin/$(MCLI_BINARY_NAME)
1111
MCLI_INSTALL_PATH="${GOPATH}/bin/$(MCLI_BINARY_NAME)"

internal/cli/root/mongocli/builder.go

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ package mongocli
1616

1717
import (
1818
"fmt"
19-
"io"
20-
"runtime"
21-
2219
"github.com/mongodb/mongocli/internal/cli"
2320
"github.com/mongodb/mongocli/internal/cli/atlas"
2421
"github.com/mongodb/mongocli/internal/cli/auth"
@@ -29,18 +26,24 @@ import (
2926
"github.com/mongodb/mongocli/internal/cli/opsmanager"
3027
"github.com/mongodb/mongocli/internal/config"
3128
"github.com/mongodb/mongocli/internal/flag"
29+
"github.com/mongodb/mongocli/internal/homebrew"
3230
"github.com/mongodb/mongocli/internal/latestrelease"
3331
"github.com/mongodb/mongocli/internal/search"
3432
"github.com/mongodb/mongocli/internal/usage"
3533
"github.com/mongodb/mongocli/internal/version"
34+
"github.com/spf13/afero"
3635
"github.com/spf13/cobra"
36+
"io"
37+
"runtime"
3738
)
3839

40+
type Notifier struct {
41+
}
42+
3943
// Builder conditionally adds children commands as needed.
4044
// This is important in particular for Atlas as it dynamically sets flags for cluster creation and
4145
// this can be slow to timeout on environments with limited internet access (Ops Manager).
4246
func Builder(profile *string, argsWithoutProg []string) *cobra.Command {
43-
4447
rootCmd := &cobra.Command{
4548
Version: version.Version,
4649
Use: config.ToolName,
@@ -58,9 +61,15 @@ func Builder(profile *string, argsWithoutProg []string) *cobra.Command {
5861
if shouldSkipPrintNewVersion(w) {
5962
return
6063
}
61-
printer := latestrelease.NewPrinter(w, config.ToolName, config.BinName())
62-
checker := latestrelease.NewChecker(version.Version, config.ToolName, printer)
64+
c, _ := homebrew.NewChecker(afero.NewOsFs())
65+
c.IsHomebrew()
66+
// p := NewPrinter(w, config.ToolName, config.BinName(), c.IsHomebrew())
67+
checker := latestrelease.NewChecker(version.Version, config.ToolName)
68+
// shouldCheck && isLatests{
69+
// print new vercions
70+
//}
6371
_ = checker.CheckAvailable()
72+
6473
},
6574
}
6675
rootCmd.SetVersionTemplate(formattedVersion())
@@ -107,6 +116,42 @@ func Builder(profile *string, argsWithoutProg []string) *cobra.Command {
107116
return rootCmd
108117
}
109118

119+
type Printer interface {
120+
PrintNewVersionAvailable(latestVersion, homebrewCommand string) error
121+
}
122+
123+
func NewPrinter(w io.Writer, t, b string) Printer {
124+
return &printer{
125+
writer: w,
126+
tool: t,
127+
bin: b,
128+
}
129+
}
130+
131+
type printer struct {
132+
writer io.Writer
133+
tool string
134+
bin string
135+
}
136+
137+
func (p *printer) PrintNewVersionAvailable(latestVersion, formulaName string) error {
138+
var upgradeInstructions string
139+
if formulaName != "" {
140+
upgradeInstructions = fmt.Sprintf(`To upgrade, run "brew update && brew upgrade %s".`, formulaName)
141+
} else {
142+
upgradeInstructions = fmt.Sprintf(`To upgrade, see: https://dochub.mongodb.org/core/%s-install.`, p.tool)
143+
}
144+
145+
newVersionTemplate := `
146+
A new version of %s is available '%s'!
147+
%s
148+
149+
To disable this alert, run "%s config set skip_update_check true".
150+
`
151+
_, err := fmt.Fprintf(p.writer, newVersionTemplate, p.tool, latestVersion, upgradeInstructions, p.bin)
152+
return err
153+
}
154+
110155
const verTemplate = `%s version: %s
111156
git version: %s
112157
Go version: %s

internal/homebrew/homebrew.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright 2022 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package homebrew
16+
17+
import (
18+
"bytes"
19+
"os"
20+
"os/exec"
21+
"path/filepath"
22+
"strings"
23+
"time"
24+
25+
"github.com/mongodb/mongocli/internal/config"
26+
"github.com/mongodb/mongocli/internal/file"
27+
"github.com/spf13/afero"
28+
)
29+
30+
//go:generate mockgen -destination=../mocks/mock_brew_store.go -package=mocks github.com/mongodb/mongocli/internal/homebrew PathStore
31+
32+
const atlasFormulaName = "mongodb-atlas"
33+
34+
// formulaName get homebrew suitable command for a given tool.
35+
func formulaName(tool string) string {
36+
if strings.Contains(tool, "atlas") {
37+
return atlasFormulaName
38+
}
39+
return tool
40+
}
41+
42+
// IsHomebrew checks if the cli was installed with homebrew.
43+
func (s Checker) IsHomebrew() bool {
44+
h, err := s.Load()
45+
// If one of the values was not found previously it is still a valid case - rely on the file.
46+
if (h.ExecutablePath != "" || h.FormulaPath != "") && err == nil {
47+
return strings.HasPrefix(h.ExecutablePath, h.FormulaPath)
48+
}
49+
formula := formulaName(config.BinName())
50+
buf := new(bytes.Buffer)
51+
cmd := exec.Command("brew", "--prefix", "--installed", formula)
52+
53+
cmd.Stdout = buf
54+
if err := cmd.Start(); err != nil {
55+
return false
56+
}
57+
58+
executablePath, err := executableCurrentPath()
59+
if err != nil {
60+
return false
61+
}
62+
h.ExecutablePath = executablePath
63+
64+
if err := cmd.Wait(); err != nil {
65+
return false
66+
}
67+
brewFormulaPath, err := filepath.EvalSymlinks(strings.TrimSpace(buf.String()))
68+
if err != nil {
69+
return false
70+
}
71+
h.FormulaPath = brewFormulaPath
72+
_ = s.Save(h)
73+
return strings.HasPrefix(executablePath, brewFormulaPath)
74+
}
75+
76+
func executableCurrentPath() (string, error) {
77+
executablePath, err := os.Executable()
78+
if err != nil {
79+
return "", err
80+
}
81+
return filepath.EvalSymlinks(executablePath)
82+
}
83+
84+
type homebrew struct {
85+
CheckedAt time.Time `yaml:"checked_at"`
86+
ExecutablePath string `yaml:"executable_path"`
87+
FormulaPath string `yaml:"formula_path"`
88+
}
89+
90+
type Loader interface {
91+
Load() (*homebrew, error)
92+
}
93+
94+
type LoaderSaver interface {
95+
Loader
96+
Save(*homebrew) error
97+
}
98+
99+
func NewChecker(fileSystem afero.Fs) (*Checker, error) {
100+
filePath, err := config.Path(brewFileSubPath)
101+
if err != nil {
102+
return nil, err
103+
}
104+
return &Checker{fs: fileSystem, path: filePath}, nil
105+
}
106+
107+
type Checker struct {
108+
path string
109+
fs afero.Fs
110+
}
111+
112+
const brewFileSubPath = "/brew.yaml"
113+
114+
// Load will load the latest calculated brew path.
115+
func (s *Checker) Load() (*homebrew, error) {
116+
path := new(homebrew)
117+
if err := file.Load(s.fs, s.path, path); err != nil {
118+
return nil, err
119+
}
120+
121+
if path != nil && time.Since(path.CheckedAt).Hours() < 24 {
122+
return path, nil
123+
}
124+
return nil, nil
125+
}
126+
127+
// Save will save the latest calculated brew path.
128+
func (s *Checker) Save(h *homebrew) error {
129+
return file.Save(s.fs, s.path, h)
130+
}

internal/homebrew/loadersaver_test.go renamed to internal/homebrew/homebrew_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
package homebrew
1919

2020
import (
21+
"fmt"
22+
"github.com/golang/mock/gomock"
23+
"github.com/mongodb/mongocli/internal/mocks"
2124
"testing"
2225

2326
"github.com/mongodb/mongocli/internal/config"
@@ -86,3 +89,29 @@ func TestFile(t *testing.T) {
8689
}
8790
})
8891
}
92+
93+
func TestOutputOpts_testIsHomebrew(t *testing.T) {
94+
tests := []struct {
95+
tool string
96+
isHb bool
97+
}{
98+
{"atlascli", false},
99+
{"mongocli", false},
100+
}
101+
102+
for _, tt := range tests {
103+
t.Run(fmt.Sprintf("%v_ishomebrew_%v", tt.tool, tt.isHb), func(t *testing.T) {
104+
ctrl := gomock.NewController(t)
105+
mockStore := mocks.NewMockPathStore(ctrl)
106+
defer ctrl.Finish()
107+
108+
mockStore.EXPECT().LoadBrewPath().Return("", "", nil)
109+
mockStore.EXPECT().SaveBrewPath(gomock.Any(), gomock.Any()).Return(nil)
110+
111+
result := IsHomebrew(mockStore)
112+
if result != tt.isHb {
113+
t.Errorf("got = %v, want %v", result, tt.isHb)
114+
}
115+
})
116+
}
117+
}

internal/homebrew/loadersaver.go

Lines changed: 0 additions & 81 deletions
This file was deleted.

0 commit comments

Comments
 (0)