├── gomup.png
├── dependency.go
├── .gitignore
├── .goreleaser.yaml
├── table.go
├── README.md
├── go.mod
├── LICENSE
├── gomup.go
├── go.sum
└── ui.go
/gomup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alihanyalcin/gomup/HEAD/gomup.png
--------------------------------------------------------------------------------
/dependency.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type dependency struct {
4 | path string
5 | name string
6 | version string
7 | updateVersion string
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | # Dependency directories (remove the comment below to include it)
15 | # vendor/
16 |
--------------------------------------------------------------------------------
/.goreleaser.yaml:
--------------------------------------------------------------------------------
1 | # This is an example .goreleaser.yml file with some sensible defaults.
2 | # Make sure to check the documentation at https://goreleaser.com
3 | before:
4 | hooks:
5 | # You may remove this if you don't use go modules.
6 | - go mod tidy
7 | builds:
8 | - env:
9 | - CGO_ENABLED=0
10 | goos:
11 | - linux
12 | - windows
13 | - darwin
14 | archives:
15 | - replacements:
16 | darwin: Darwin
17 | linux: Linux
18 | windows: Windows
19 | 386: i386
20 | amd64: x86_64
21 | checksum:
22 | name_template: 'checksums.txt'
23 | snapshot:
24 | name_template: "{{ incpatch .Version }}-next"
25 | changelog:
26 | sort: asc
27 | filters:
28 | exclude:
29 | - '^docs:'
30 | - '^test:'
31 |
--------------------------------------------------------------------------------
/table.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/olekukonko/tablewriter"
7 | )
8 |
9 | func drawTable(dependencies []dependency) {
10 | var data [][]string
11 | for _, v := range dependencies {
12 | data = append(data, []string{
13 | v.path,
14 | v.name,
15 | v.version,
16 | v.updateVersion,
17 | })
18 | }
19 |
20 | table := tablewriter.NewWriter(os.Stdout)
21 | table.SetHeader([]string{"Path", "Name", "Current Version", "Update Version"})
22 | table.SetAutoMergeCells(true)
23 | table.SetRowLine(true)
24 |
25 | var color = []tablewriter.Colors{
26 | {tablewriter.Bold, tablewriter.FgMagentaColor},
27 | {tablewriter.FgCyanColor},
28 | {tablewriter.Bold},
29 | {tablewriter.Bold},
30 | }
31 |
32 | for _, v := range data {
33 | table.Rich(v, color)
34 | }
35 | table.Render()
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gomUP 🆙
2 |
3 | gomUP is a tool to keep track of outdated dependencies and upgrade them to the latest version. Designed for monorepo Go
4 | projects and Go projects that contain multiple modules.
5 |
6 | 
7 |
8 | # Install
9 |
10 | Go to the [releases page](https://github.com/alihanyalcin/gomup/releases), and download the binaries for your operating
11 | system (macOS, Linux, and Windows).
12 | Alternatively,
13 | You can install it using `go install`:
14 |
15 | ```
16 | go install github.com/alihanyalcin/gomup@latest
17 | ```
18 |
19 | Or, use `homebrew`:
20 |
21 | ```
22 | brew tap alihanyalcin/gomup
23 | brew install gomup
24 | ```
25 |
26 | # Usage
27 |
28 | ```
29 | gomup -p
30 | ```
31 |
32 | After you hit the enter, **gomUP** starts to walk through your project directory path to find go modules. It may take a
33 | while to collect all modules and dependencies.
34 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/alihanyalcin/gomup
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/briandowns/spinner v1.18.0
7 | github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1
8 | github.com/olekukonko/tablewriter v0.0.5
9 | github.com/rivo/tview v0.0.0-20220106183741-90d72bc664f5
10 | github.com/urfave/cli/v2 v2.3.0
11 | )
12 |
13 | require (
14 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
15 | github.com/fatih/color v1.7.0 // indirect
16 | github.com/gdamore/encoding v1.0.0 // indirect
17 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
18 | github.com/mattn/go-colorable v0.1.2 // indirect
19 | github.com/mattn/go-isatty v0.0.8 // indirect
20 | github.com/mattn/go-runewidth v0.0.13 // indirect
21 | github.com/rivo/uniseg v0.2.0 // indirect
22 | github.com/russross/blackfriday/v2 v2.0.1 // indirect
23 | github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
24 | golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 // indirect
25 | golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
26 | golang.org/x/text v0.3.6 // indirect
27 | )
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alihan Doğuş Yalçın
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/gomup.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 | "os/exec"
8 | "path/filepath"
9 | "strings"
10 | "sync"
11 | "time"
12 |
13 | "github.com/briandowns/spinner"
14 | "github.com/urfave/cli/v2"
15 | )
16 |
17 | const gomod = "go.mod"
18 |
19 | var args = []string{
20 | "list",
21 | "-u",
22 | "-mod=mod",
23 | "-f",
24 | "'{{if (and (not (or .Main .Indirect)) .Update)}}{{.Path}} {{.Version}} {{.Update.Version}}{{end}}'",
25 | "-m",
26 | "all",
27 | }
28 |
29 | func main() {
30 | var (
31 | path string
32 | list bool
33 | )
34 |
35 | app := &cli.App{
36 | Name: "gomUP",
37 | Usage: "go module dependency upgrade tool",
38 | Flags: []cli.Flag{
39 | &cli.StringFlag{
40 | Name: "path",
41 | Aliases: []string{"p"},
42 | Usage: "directory path of go projects",
43 | Required: true,
44 | Destination: &path,
45 | },
46 | &cli.BoolFlag{
47 | Name: "list",
48 | Aliases: []string{"l"},
49 | Usage: "list all dependencies",
50 | Required: false,
51 | Destination: &list,
52 | },
53 | },
54 | Action: func(c *cli.Context) error {
55 | err := checkPath(path)
56 | if err != nil {
57 | return err
58 | }
59 |
60 | s := spinner.New(spinner.CharSets[36], 250*time.Millisecond)
61 | s.Prefix = "Starting gomUP "
62 | s.Start()
63 |
64 | dependencies := find(path)
65 |
66 | s.Stop()
67 |
68 | if len(dependencies) == 0 {
69 | fmt.Println("everything up-to-date")
70 | return nil
71 | }
72 |
73 | if list {
74 | drawTable(dependencies)
75 | return nil
76 | }
77 |
78 | startUI(dependencies)
79 |
80 | return nil
81 | },
82 | UseShortOptionHandling: true,
83 | EnableBashCompletion: true,
84 | }
85 |
86 | err := app.Run(os.Args)
87 | if err != nil {
88 | log.Fatal(err)
89 | }
90 | }
91 |
92 | func checkPath(path string) error {
93 | info, err := os.Stat(path)
94 | if os.IsNotExist(err) {
95 | return err
96 | }
97 |
98 | if !info.IsDir() {
99 | return fmt.Errorf("%s is not a directory", path)
100 | }
101 |
102 | return nil
103 | }
104 |
105 | func find(path string) []dependency {
106 | var wg sync.WaitGroup
107 | var dependencies []dependency
108 |
109 | err := filepath.Walk(path,
110 | func(path string, info os.FileInfo, err error) error {
111 | if err != nil {
112 | return err
113 | }
114 |
115 | if info.Name() == gomod {
116 | wg.Add(1)
117 | go func() {
118 | defer wg.Done()
119 |
120 | modPath := path[:(len(path) - len(gomod))]
121 | dep, err := findDepencencies(modPath)
122 | if err != nil {
123 | return
124 | }
125 | dependencies = append(dependencies, dep...)
126 | }()
127 | }
128 |
129 | return nil
130 | })
131 | if err != nil {
132 | log.Println(err)
133 | }
134 |
135 | wg.Wait()
136 |
137 | return dependencies
138 | }
139 |
140 | func findDepencencies(path string) ([]dependency, error) {
141 | var dependencies []dependency
142 |
143 | cmd := exec.Command("go", args...)
144 | cmd.Dir = path
145 | list, err := cmd.Output()
146 | if err != nil {
147 | return nil, fmt.Errorf("cannot get %s available minor and patch upgrades. error: %w", path, err)
148 | }
149 |
150 | for _, dep := range strings.Split(string(list), "\n") {
151 | if dep != "''" && dep != "" {
152 | dep = strings.Trim(dep, "'")
153 | d := strings.Split(strings.Trim(dep, "'"), " ")
154 | dependencies = append(dependencies, dependency{
155 | path: path,
156 | name: d[0],
157 | version: d[1],
158 | updateVersion: d[2],
159 | })
160 | }
161 | }
162 |
163 | return dependencies, nil
164 | }
165 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2 | github.com/briandowns/spinner v1.18.0 h1:SJs0maNOs4FqhBwiJ3Gr7Z1D39/rukIVGQvpNZVHVcM=
3 | github.com/briandowns/spinner v1.18.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
4 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
5 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
6 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
7 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
8 | github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
9 | github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
10 | github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1 h1:QqwPZCwh/k1uYqq6uXSb9TRDhTkfQbO80v8zhnIe5zM=
11 | github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04=
12 | github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
13 | github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
14 | github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
15 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
16 | github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
17 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
18 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
19 | github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
20 | github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
21 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
22 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
23 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
24 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
25 | github.com/rivo/tview v0.0.0-20220106183741-90d72bc664f5 h1:n0qwaaNXgplKv5AeDIzpXnwoLh9ddQzVsAY8d7WiZvs=
26 | github.com/rivo/tview v0.0.0-20220106183741-90d72bc664f5/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk=
27 | github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
28 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
29 | github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
30 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
31 | github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
32 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
33 | github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
34 | github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
35 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
36 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
37 | golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY=
38 | golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
39 | golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
40 | golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
41 | golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
42 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
43 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
44 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
45 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
46 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
47 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
48 |
--------------------------------------------------------------------------------
/ui.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os/exec"
6 | "sort"
7 |
8 | "github.com/gdamore/tcell/v2"
9 | "github.com/rivo/tview"
10 | )
11 |
12 | type view struct {
13 | app *tview.Application
14 | pages *tview.Pages
15 | table *tview.Table
16 | update *tview.Modal
17 | quit *tview.Modal
18 | info *tview.Modal
19 | dependencies []dependency
20 | }
21 |
22 | func startUI(d []dependency) {
23 | sort.Slice(d, func(i, j int) bool {
24 | return d[i].path < d[j].path
25 | })
26 |
27 | v := &view{
28 | app: tview.NewApplication(),
29 | pages: tview.NewPages(),
30 | table: tview.NewTable(),
31 | update: tview.NewModal(),
32 | quit: tview.NewModal(),
33 | info: tview.NewModal(),
34 | dependencies: d,
35 | }
36 |
37 | v.setInfoModal()
38 | v.setUpdateModal()
39 | v.setQuitModal()
40 | v.setTable()
41 |
42 | if err := v.app.SetRoot(v.pages, true).SetFocus(v.table).EnableMouse(true).Run(); err != nil {
43 | panic(err)
44 | }
45 | }
46 |
47 | func (v *view) setInfoModal() {
48 | v.info.AddButtons([]string{"OK"}).
49 | SetDoneFunc(func(buttonIndex int, buttonLabel string) {
50 | v.pages.SendToBack("info")
51 | })
52 |
53 | v.pages.AddPage("info", v.info, true, true)
54 | v.pages.SendToBack("info")
55 | }
56 |
57 | func (v *view) setUpdateModal() {
58 | v.update.AddButtons([]string{"Yes", "No"})
59 |
60 | v.pages.AddPage("update", v.update, true, true)
61 | v.pages.SendToBack("update")
62 | }
63 |
64 | func (v *view) setQuitModal() {
65 | v.quit.SetText("Do you want to quit?").
66 | AddButtons([]string{"Quit", "Cancel"}).
67 | SetDoneFunc(func(buttonIndex int, buttonLabel string) {
68 | if buttonLabel == "Quit" {
69 | v.app.Stop()
70 | } else {
71 | v.pages.SendToBack("quit")
72 | }
73 | })
74 |
75 | v.pages.AddPage("quit", v.quit, true, true)
76 | v.pages.SendToBack("quit")
77 | }
78 |
79 | func (v *view) setTable() {
80 | v.table.SetBorder(true).SetTitle("gomUP - ESC: quit - ENTER: upgrade").SetTitleAlign(tview.AlignCenter)
81 |
82 | colsHeader := []string{"PATH", "NAME", "CURRENT VERSION", "UPDATE VERSION"}
83 | cols, rows := len(colsHeader), len(v.dependencies)+1
84 | for r := 0; r < rows; r++ {
85 | for c := 0; c < cols; c++ {
86 | color := tcell.ColorWhite
87 | if c == 0 && r != 0 {
88 | color = tcell.ColorAquaMarine
89 | } else if c != 0 && r != 0 {
90 | color = tcell.ColorRed
91 | }
92 |
93 | align := tview.AlignLeft
94 | if r == 0 {
95 | align = tview.AlignCenter
96 | } else if c == 0 {
97 | align = tview.AlignRight
98 | }
99 |
100 | var tableCell *tview.TableCell
101 | if r == 0 {
102 | // Set Headers
103 | tableCell = tview.NewTableCell(colsHeader[c]).
104 | SetTextColor(color).
105 | SetAlign(align).
106 | SetSelectable(false).
107 | SetAttributes(tcell.AttrBold)
108 | } else {
109 | tableCell = tview.NewTableCell(v.getString(r-1, c)).
110 | SetTextColor(color).
111 | SetAlign(align).
112 | SetSelectable(c != 0)
113 | }
114 |
115 | v.table.SetCell(r, c, tableCell)
116 |
117 | if c > 0 && c < 4 {
118 | tableCell.SetExpansion(1)
119 | }
120 | }
121 | }
122 |
123 | v.table.SetBorders(true)
124 | v.table.SetSelectable(true, false)
125 | v.table.Select(1, 0).SetFixed(1, 0).
126 | SetDoneFunc(func(key tcell.Key) {
127 | if key == tcell.KeyEscape {
128 | v.pages.SendToFront("quit")
129 | }
130 | }).
131 | SetSelectedFunc(func(row int, column int) {
132 | dependency := v.dependencies[row-1]
133 | v.pages.SendToFront("update")
134 | v.update.SetText(fmt.Sprintf("Do you want to upgrade %s for %s?", dependency.name, dependency.path)).
135 | SetDoneFunc(func(buttonIndex int, buttonLabel string) {
136 | v.pages.SendToBack("update")
137 | if buttonLabel == "Yes" {
138 | v.upgrade(row, cols)
139 | }
140 |
141 | })
142 | })
143 |
144 | v.pages.AddPage("table", v.table, true, true)
145 | }
146 |
147 | func (v *view) upgrade(row, cols int) {
148 | v.pages.SendToFront("info")
149 |
150 | dependency := v.dependencies[row-1]
151 |
152 | cmd := exec.Command("go", "get", dependency.name)
153 | cmd.Dir = dependency.path
154 | _, err := cmd.Output()
155 | if err != nil {
156 | v.info.SetText("Error occured: " + err.Error())
157 | } else {
158 | v.info.SetText("Success!")
159 |
160 | for c := 1; c < cols; c++ {
161 | v.table.GetCell(row, c).SetTextColor(tcell.ColorAquaMarine).SetSelectable(false)
162 | }
163 | }
164 | }
165 |
166 | func (v *view) getString(row, col int) string {
167 | value := v.dependencies[row]
168 | return []string{value.path, value.name, value.version, value.updateVersion}[col]
169 | }
170 |
--------------------------------------------------------------------------------