diff --git a/Changelog.md b/Changelog.md index 392ba71..e313e68 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,9 @@ # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# [0.9.0] - 2022-03-18 +## Added +- Added desktop notification: gup command will notify you on your desktop whether the update was successful or unsuccessful after the update was finished. # [0.8.0] - 2022-03-18 ## Added - Added check subcommand: get the latest version of the binary installed by 'go install'" diff --git a/README.md b/README.md index c60062a..52c69be 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,13 @@ ![GitHub](https://img.shields.io/github/license/nao1215/gup) [[日本語](./doc/ja/README.md)] # gup - Update binaries installed by "go install" -**gup** command update binaries installed by "go install" to the latest version. It also provides subcommands for manipulating binaries under \$GOPATH/bin (\$GOBIN). +**gup** command update binaries installed by "go install" to the latest version. It also provides subcommands for manipulating binaries under \$GOPATH/bin (\$GOBIN). It is a cross-platform software that runs on Windows, Mac and Linux. ![sample](./doc/img/sample.png) + +gup command will notify you on your desktop whether the update was successful or unsuccessful after the update was finished. +![success](./doc/img/notify_success.png) +![warning](./doc/img/notify_warning.png) + # How to install ### Step.1 Install golang gup command only supports installation with `$ go install`. If you does not have the golang development environment installed on your system, please install golang from the [golang official website](https://go.dev/doc/install). diff --git a/cmd/root.go b/cmd/root.go index b24d387..d2bbf8a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,7 @@ package cmd import ( + "github.com/nao1215/gup/internal/assets" "github.com/nao1215/gup/internal/print" "github.com/spf13/cobra" ) @@ -13,6 +14,7 @@ If you update all binaries, just run '$ gup update'`, // Execute run gup process. func Execute() { + assets.DeployIconIfNeeded() if err := rootCmd.Execute(); err != nil { print.Err(err) } diff --git a/cmd/update.go b/cmd/update.go index 1864819..b2b8575 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -9,6 +9,7 @@ import ( "time" "github.com/nao1215/gup/internal/goutil" + "github.com/nao1215/gup/internal/notify" "github.com/nao1215/gup/internal/print" "github.com/nao1215/gup/internal/slice" "github.com/spf13/cobra" @@ -65,6 +66,7 @@ func update(pkgs []goutil.Package, dryRun bool) int { if dryRun { if err := dryRunManager.StartDryRunMode(); err != nil { print.Err(fmt.Errorf("can not change to dry run mode: %w", err)) + notify.Warn("gup", "Can not change to dry run mode") return 1 } signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, @@ -99,6 +101,12 @@ func update(pkgs []goutil.Package, dryRun bool) int { } close(signals) } + + if result == 0 { + notify.Info("gup", "All update success") + } else { + notify.Warn("gup", "Some package can't update") + } return result } diff --git a/doc/img/notify_success.png b/doc/img/notify_success.png new file mode 100644 index 0000000..7c27310 Binary files /dev/null and b/doc/img/notify_success.png differ diff --git a/doc/img/notify_warning.png b/doc/img/notify_warning.png new file mode 100644 index 0000000..a2167f0 Binary files /dev/null and b/doc/img/notify_warning.png differ diff --git a/doc/ja/README.md b/doc/ja/README.md index 8aefbb1..b528361 100644 --- a/doc/ja/README.md +++ b/doc/ja/README.md @@ -2,8 +2,12 @@ [![UnitTest](https://github.com/nao1215/gup/actions/workflows/unit_test.yml/badge.svg)](https://github.com/nao1215/gup/actions/workflows/unit_test.yml) [![reviewdog](https://github.com/nao1215/gup/actions/workflows/reviewdog.yml/badge.svg)](https://github.com/nao1215/gup/actions/workflows/reviewdog.yml) # gupとは -**gup**コマンドは、"go install"でインストールしたバイナリを最新版にアップデートします。gupは、\$GOPATH/bin (\$GOBIN) 以下にあるバイナリをするためのサブコマンドも提供しています。 +**gup**コマンドは、"go install"でインストールしたバイナリを最新版にアップデートします。gupは、\$GOPATH/bin (\$GOBIN) 以下にあるバイナリをするためのサブコマンドも提供しています。クロスプラットホームソフトであり、Windows, Mac, Linux で動作します。 ![sample](../img/sample.png) + +gupコマンドはアップデートが終わった後、成功したか失敗したかをデスクトップ通知します。 +![success](..//img/notify_success.png) +![warning](../img/notify_warning.png) # インストール方法 ### Step.1 前準備 現在は、" $ go install"によるインストールのみをサポートしています。そのため、golangの開発環境をシステムにインストールしていない場合、[golang公式サイト](https://go.dev/doc/install)からgolangをインストールしてください。 diff --git a/go.mod b/go.mod index fb4220a..ce29502 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,20 @@ go 1.17 require ( github.com/fatih/color v1.13.0 + github.com/gen2brain/beeep v0.0.0-20210529141713-5586760f0cc1 github.com/mattn/go-colorable v0.1.12 github.com/spf13/cobra v1.4.0 ) require ( + github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 // indirect + github.com/godbus/dbus/v5 v5.0.3 // indirect + github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c // indirect + github.com/gopherjs/gopherwasm v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect ) diff --git a/go.sum b/go.sum index a2cfec5..1201146 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,16 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/gen2brain/beeep v0.0.0-20210529141713-5586760f0cc1 h1:Xh9mvwEmhbdXlRSsgn+N0zj/NqnKvpeqL08oKDHln2s= +github.com/gen2brain/beeep v0.0.0-20210529141713-5586760f0cc1/go.mod h1:ElSskYZe3oM8kThaHGJ+kiN2yyUMVXMZ7WxF9QqLDS8= +github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE= +github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= +github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherwasm v1.1.0 h1:fA2uLoctU5+T3OhOn2vYP0DVT6pxc7xhTlBB1paATqQ= +github.com/gopherjs/gopherwasm v1.1.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -9,13 +19,18 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= +github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk= +github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= diff --git a/internal/assets/asset.go b/internal/assets/asset.go new file mode 100644 index 0000000..c9740b1 --- /dev/null +++ b/internal/assets/asset.go @@ -0,0 +1,56 @@ +package assets + +import ( + _ "embed" + "fmt" + "os" + "path/filepath" + + "github.com/nao1215/gup/internal/config" + "github.com/nao1215/gup/internal/file" + "github.com/nao1215/gup/internal/print" +) + +//go:embed information.png +var inforIcon []byte + +//go:embed warning.png +var warningIcon []byte + +// DeployIconIfNeeded make icon file for notification. +func DeployIconIfNeeded() { + if !file.IsDir(assetsDirPath()) { + if err := os.MkdirAll(assetsDirPath(), 0775); err != nil { + print.Err(fmt.Errorf("%s: %w", "can not make assets directory", err)) + return + } + } + + if !file.IsFile(InfoIconPath()) { + err := os.WriteFile(InfoIconPath(), inforIcon, 0664) + if err != nil { + print.Warn(err) + } + } + if !file.IsFile(WarningIconPath()) { + err := os.WriteFile(WarningIconPath(), warningIcon, 0664) + if err != nil { + print.Warn(err) + } + } +} + +// InfoIconPath return absolute path of information.png +func InfoIconPath() string { + return filepath.Join(assetsDirPath(), "information.png") +} + +// WarningIconPath return absolute path of information.png +func WarningIconPath() string { + return filepath.Join(assetsDirPath(), "warning.png") +} + +// assetsDirPath return absolute path of assets directory +func assetsDirPath() string { + return filepath.Join(config.DirPath(), "assets") +} diff --git a/internal/assets/information.png b/internal/assets/information.png new file mode 100644 index 0000000..d47243d Binary files /dev/null and b/internal/assets/information.png differ diff --git a/internal/assets/warning.png b/internal/assets/warning.png new file mode 100644 index 0000000..3c63d16 Binary files /dev/null and b/internal/assets/warning.png differ diff --git a/internal/cmdinfo/cmdinfo.go b/internal/cmdinfo/cmdinfo.go index 8ad2277..af1b481 100644 --- a/internal/cmdinfo/cmdinfo.go +++ b/internal/cmdinfo/cmdinfo.go @@ -6,7 +6,7 @@ import ( const ( name = "gup" - version = "0.8.0" + version = "0.9.0" ) // Version return gup command version. diff --git a/internal/config/config.go b/internal/config/config.go index 487a036..a7718d5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,6 +1,7 @@ package config import ( + _ "embed" "fmt" "os" "path/filepath" diff --git a/internal/file/file.go b/internal/file/file.go index 44a81b5..d079e8b 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -34,3 +34,9 @@ func IsFile(path string) bool { stat, err := os.Stat(path) return (err == nil) && (!stat.IsDir()) } + +// IsDir reports whether the path exists and is a directory. +func IsDir(path string) bool { + stat, err := os.Stat(path) + return (err == nil) && (stat.IsDir()) +} diff --git a/internal/notify/notify.go b/internal/notify/notify.go new file mode 100644 index 0000000..7986bec --- /dev/null +++ b/internal/notify/notify.go @@ -0,0 +1,23 @@ +package notify + +import ( + "github.com/gen2brain/beeep" + "github.com/nao1215/gup/internal/assets" + "github.com/nao1215/gup/internal/print" +) + +// Info notify information message at desktop +func Info(title, message string) { + err := beeep.Notify(title, message, assets.InfoIconPath()) + if err != nil { + print.Warn(err) + } +} + +// Warn notify warning message at desktop +func Warn(title, message string) { + err := beeep.Notify(title, message, assets.WarningIconPath()) + if err != nil { + print.Warn(err) + } +}