github.com/mattdotmatt/gauge@v0.3.2-0.20160421115137-425a4cdccb62/plugin/install/check.go (about) 1 // Copyright 2015 ThoughtWorks, Inc. 2 3 // This file is part of Gauge. 4 5 // Gauge is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 10 // Gauge is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with Gauge. If not, see <http://www.gnu.org/licenses/>. 17 18 package install 19 20 import ( 21 "fmt" 22 "io" 23 "net/http" 24 "strings" 25 "sync" 26 27 "github.com/dmotylev/goproperties" 28 "github.com/getgauge/gauge/config" 29 "github.com/getgauge/gauge/logger" 30 "github.com/getgauge/gauge/plugin" 31 "github.com/getgauge/gauge/version" 32 ) 33 34 type UpdateFacade struct { 35 wg *sync.WaitGroup 36 print chan bool 37 } 38 39 func (u *UpdateFacade) BufferUpdateDetails() { 40 var wg sync.WaitGroup 41 u.print = make(chan bool) 42 u.wg = &wg 43 u.wg.Add(1) 44 go printUpdateInfo(u.print, u.wg) 45 } 46 47 func (u *UpdateFacade) PrintUpdateBuffer() { 48 u.print <- true 49 u.wg.Wait() 50 } 51 52 func PrintUpdateInfoWithDetails() { 53 updates := checkUpdates() 54 if len(updates) > 0 { 55 for _, update := range updates { 56 logger.Info(fmt.Sprintf("%-10s\t\t%-10s\t%s", update.Name, update.CompatibleVersion, update.Message)) 57 } 58 } else { 59 logger.Info("No Updates available.") 60 } 61 } 62 63 func checkUpdates() []UpdateInfo { 64 return append(checkGaugeUpdate(), checkPluginUpdates()...) 65 } 66 67 func printUpdateInfo(print chan bool, wg *sync.WaitGroup) { 68 message := make(chan string) 69 go func() { 70 updates := checkUpdates() 71 if len(updates) > 0 { 72 message <- "Updates are available. Run gauge --check-updates for more info." 73 } 74 }() 75 waitToPrint(message, print, "", wg) 76 } 77 78 func waitToPrint(messageChan chan string, printChan chan bool, message string, wg *sync.WaitGroup) { 79 select { 80 case <-printChan: 81 if message != "" { 82 logger.Info(message) 83 } 84 wg.Done() 85 case message = <-messageChan: 86 waitToPrint(messageChan, printChan, message, wg) 87 } 88 } 89 90 func checkGaugeUpdate() []UpdateInfo { 91 var updateInfos []UpdateInfo 92 url := config.GaugeUpdateUrl() 93 if qp := plugin.QueryParams(); qp != "" { 94 url += qp 95 } 96 v, err := getLatestGaugeVersion(url) 97 if err != nil { 98 return updateInfos 99 } 100 latestVersion, err := version.ParseVersion(v) 101 if err != nil { 102 return updateInfos 103 } 104 isLatestVersion := version.CurrentGaugeVersion.IsLesserThan(latestVersion) 105 if isLatestVersion { 106 updateInfos = append(updateInfos, UpdateInfo{"Gauge", latestVersion.String(), "Download the installer from http://getgauge.io/get-started/"}) 107 } 108 return updateInfos 109 } 110 111 type UpdateInfo struct { 112 Name string 113 CompatibleVersion string 114 Message string 115 } 116 117 func checkPluginUpdates() []UpdateInfo { 118 var pluginsToUpdate []UpdateInfo 119 plugins, err := plugin.GetAllInstalledPluginsWithVersion() 120 if err != nil { 121 return pluginsToUpdate 122 } 123 logger.Debug("Checking updates...") 124 for _, plugin := range plugins { 125 desc, result := getInstallDescription(plugin.Name, true) 126 if result.Error != nil { 127 continue 128 } 129 pluginsToUpdate = append(pluginsToUpdate, createPluginUpdateDetail(plugin.Version.String(), *desc)...) 130 } 131 return pluginsToUpdate 132 } 133 134 func createPluginUpdateDetail(currentVersion string, latestVersionDetails installDescription) []UpdateInfo { 135 var updateInfo []UpdateInfo 136 v, _ := version.ParseVersion(currentVersion) 137 v1, _ := version.ParseVersion(latestVersionDetails.Versions[0].Version) 138 if v.IsLesserThan(v1) { 139 versionDesc, err := latestVersionDetails.getLatestCompatibleVersionTo(version.CurrentGaugeVersion) 140 if err != nil { 141 return updateInfo 142 } 143 updateInfo = append(updateInfo, UpdateInfo{latestVersionDetails.Name, versionDesc.Version, fmt.Sprintf("Run 'gauge --update %s'", latestVersionDetails.Name)}) 144 } 145 return updateInfo 146 } 147 148 var getLatestGaugeVersion = func(url string) (string, error) { 149 res, err := http.Get(url) 150 if err != nil { 151 return "", err 152 } 153 defer res.Body.Close() 154 155 v, err := getGaugeVersionProperty(res.Body) 156 if err != nil { 157 return "", err 158 } 159 return v, nil 160 } 161 162 func getGaugeVersionProperty(r io.Reader) (string, error) { 163 properties := make(properties.Properties) 164 165 err := properties.Load(r) 166 if err != nil { 167 return "", fmt.Errorf("Failed to parse: %s", err.Error()) 168 } 169 return strings.TrimSpace(properties["version"]), nil 170 }