From b60aa54db68385d0d7d050b0eb55403a347f99cd Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Wed, 25 Jul 2018 12:56:56 +0200 Subject: [PATCH 1/4] Handle config better Eliminated iniflags, used a flagset to handle inheritance of config. Changing config restarts the process (so that it can be instantiated again) --- config.ini | 3 +- hub.go | 13 +- info.go | 12 +- main.go | 424 ++++++++++-------- trayicon.go | 16 +- .../github.com/vharitonsky/iniflags/LICENSE | 23 - .../github.com/vharitonsky/iniflags/README.md | 141 ------ .../vharitonsky/iniflags/iniflags.go | 409 ----------------- .../vharitonsky/iniflags/test_bom.ini | 1 - .../vharitonsky/iniflags/test_config.ini | 8 - .../vharitonsky/iniflags/test_config2.ini | 3 - .../iniflags/test_setconfigfile.ini | 1 - vendor/vendor.json | 5 - 13 files changed, 247 insertions(+), 812 deletions(-) delete mode 100644 vendor/github.com/vharitonsky/iniflags/LICENSE delete mode 100644 vendor/github.com/vharitonsky/iniflags/README.md delete mode 100644 vendor/github.com/vharitonsky/iniflags/iniflags.go delete mode 100644 vendor/github.com/vharitonsky/iniflags/test_bom.ini delete mode 100644 vendor/github.com/vharitonsky/iniflags/test_config.ini delete mode 100644 vendor/github.com/vharitonsky/iniflags/test_config2.ini delete mode 100644 vendor/github.com/vharitonsky/iniflags/test_setconfigfile.ini diff --git a/config.ini b/config.ini index fa12c9b2a..3c4348aa2 100644 --- a/config.ini +++ b/config.ini @@ -1,8 +1,7 @@ -configUpdateInterval = 0 # Update interval for re-reading config file set via -config flag. Zero disables config file re-reading. gc = std # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage) hostname = unknown-hostname # Override the hostname we get from the OS -ls = false # launch self 5 seconds later regex = usb|acm|com # Regular expression to filter serial port list v = true # show debug logging appName = CreateBridge updateUrl = http://downloads.arduino.cc/ +origins = http://downloads.arduino.cc/ diff --git a/hub.go b/hub.go index 45aacffd0..9b0744970 100755 --- a/hub.go +++ b/hub.go @@ -276,7 +276,7 @@ func exit() { } -func restart(path string) { +func restart(path string, args ...string) { log.Println("called restart", path) quitSysTray() // relaunch ourself and exit @@ -302,14 +302,9 @@ func restart(path string) { exePath = strings.Trim(exePath, "\n") - hiberString := "" - if *hibernate == true { - hiberString = "-hibernate" - } - - cmd := exec.Command(exePath, "-ls", "-regex", *regExpFilter, "-gc", *gcType, hiberString) - - fmt.Println(cmd) + args = append(args, "-ls") + args = append(args, "-hibernate="+fmt.Sprint(*hibernate)) + cmd := exec.Command(exePath, args...) err := cmd.Start() if err != nil { diff --git a/info.go b/info.go index 8a84e479a..ad694fc47 100644 --- a/info.go +++ b/info.go @@ -13,12 +13,12 @@ func infoHandler(c *gin.Context) { host = parts[0] c.JSON(200, gin.H{ - "version": version, - "http": "http://" + host + port, - "https": "https://localhost" + portSSL, - "ws": "ws://" + host + port, - "wss": "wss://localhost" + portSSL, - "origins": origins, + "version": version, + "http": "http://" + host + port, + "https": "https://localhost" + portSSL, + "ws": "ws://" + host + port, + "wss": "wss://localhost" + portSSL, + "origins": origins, "update_url": updateUrl, }) } diff --git a/main.go b/main.go index 6f36328d8..3fdc8177e 100755 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ package main import ( "encoding/json" "flag" + "fmt" "os" "os/user" "path/filepath" @@ -15,13 +16,14 @@ import ( "text/template" "time" + "github.com/go-ini/ini" + log "github.com/Sirupsen/logrus" "github.com/arduino/arduino-create-agent/tools" "github.com/arduino/arduino-create-agent/utilities" "github.com/gin-gonic/gin" cors "github.com/itsjamie/gin-cors" "github.com/kardianos/osext" - "github.com/vharitonsky/iniflags" //"github.com/sanbornm/go-selfupdate/selfupdate" #included in update.go to change heavily ) @@ -29,27 +31,40 @@ var ( version = "x.x.x-dev" //don't modify it, Jenkins will take care git_revision = "xxxxxxxx" //don't modify it, Jenkins will take care embedded_autoextract = false - hibernate = flag.Bool("hibernate", false, "start hibernated") - verbose = flag.Bool("v", true, "show debug logging") - isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later") - configIni = flag.String("configFile", "config.ini", "config file path") - regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list") - gcType = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)") - logDump = flag.String("log", "off", "off = (default)") - hostname = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS") - updateUrl = flag.String("updateUrl", "", "") - appName = flag.String("appName", "", "") - genCert = flag.Bool("generateCert", false, "") port string portSSL string - origins = flag.String("origins", "", "Allowed origin list for CORS") - address = flag.String("address", "127.0.0.1", "The address where to listen. Defaults to localhost") - signatureKey = flag.String("signatureKey", "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvc0yZr1yUSen7qmE3cxF\nIE12rCksDnqR+Hp7o0nGi9123eCSFcJ7CkIRC8F+8JMhgI3zNqn4cUEn47I3RKD1\nZChPUCMiJCvbLbloxfdJrUi7gcSgUXrlKQStOKF5Iz7xv1M4XOP3JtjXLGo3EnJ1\npFgdWTOyoSrA8/w1rck4c/ISXZSinVAggPxmLwVEAAln6Itj6giIZHKvA2fL2o8z\nCeK057Lu8X6u2CG8tRWSQzVoKIQw/PKK6CNXCAy8vo4EkXudRutnEYHEJlPkVgPn\n2qP06GI+I+9zKE37iqj0k1/wFaCVXHXIvn06YrmjQw6I0dDj/60Wvi500FuRVpn9\ntwIDAQAB\n-----END PUBLIC KEY-----", "Pem-encoded public key to verify signed commandlines") - Tools tools.Tools - indexURL = flag.String("indexURL", "https://downloads.arduino.cc/packages/package_staging_index.json", "The address from where to download the index json containing the location of upload tools") requiredToolsAPILevel = "v1" ) +// regular flags +var ( + hibernate = flag.Bool("hibernate", false, "start hibernated") + genCert = flag.Bool("generateCert", false, "") + additionalConfig = flag.String("additional-config", "config.ini", "config file path") + isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later") +) + +// iniflags +var ( + iniConf = flag.NewFlagSet("ini", flag.ContinueOnError) + address = iniConf.String("address", "127.0.0.1", "The address where to listen. Defaults to localhost") + appName = iniConf.String("appName", "", "") + gcType = iniConf.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)") + hostname = iniConf.String("hostname", "unknown-hostname", "Override the hostname we get from the OS") + indexURL = iniConf.String("indexURL", "https://downloads.arduino.cc/packages/package_staging_index.json", "The address from where to download the index json containing the location of upload tools") + logDump = iniConf.String("log", "off", "off = (default)") + origins = iniConf.String("origins", "", "Allowed origin list for CORS") + regExpFilter = iniConf.String("regex", "usb|acm|com", "Regular expression to filter serial port list") + signatureKey = iniConf.String("signatureKey", "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvc0yZr1yUSen7qmE3cxF\nIE12rCksDnqR+Hp7o0nGi9123eCSFcJ7CkIRC8F+8JMhgI3zNqn4cUEn47I3RKD1\nZChPUCMiJCvbLbloxfdJrUi7gcSgUXrlKQStOKF5Iz7xv1M4XOP3JtjXLGo3EnJ1\npFgdWTOyoSrA8/w1rck4c/ISXZSinVAggPxmLwVEAAln6Itj6giIZHKvA2fL2o8z\nCeK057Lu8X6u2CG8tRWSQzVoKIQw/PKK6CNXCAy8vo4EkXudRutnEYHEJlPkVgPn\n2qP06GI+I+9zKE37iqj0k1/wFaCVXHXIvn06YrmjQw6I0dDj/60Wvi500FuRVpn9\ntwIDAQAB\n-----END PUBLIC KEY-----", "Pem-encoded public key to verify signed commandlines") + updateUrl = iniConf.String("updateUrl", "", "") + verbose = iniConf.Bool("v", true, "show debug logging") +) + +// global clients +var ( + Tools tools.Tools +) + type NullWriter int func (NullWriter) Write([]byte) (int, error) { return 0, nil } @@ -74,197 +89,201 @@ func launchSelfLater() { } func main() { - + // Parse regular flags flag.Parse() + // Generate certificates if *genCert == true { generateCertificates() os.Exit(0) } + fmt.Println(*hibernate) + if *hibernate == false { + // autoextract self + src, _ := osext.Executable() + dest := filepath.Dir(src) + + if embedded_autoextract { + // save the config.ini (if it exists) + if _, err := os.Stat(filepath.Join(dest, "config.ini")); os.IsNotExist(err) { + log.Println("First run, unzipping self") + err := utilities.Unzip(src, dest) + log.Println("Self extraction, err:", err) + } + } + + // Parse ini config + args, err := parseIni("config.ini") + fmt.Println(args) + if err != nil { + panic(err) + } + err = iniConf.Parse(args) + if err != nil { + panic(err) + } + + // Parse additional ini config + args, err = parseIni(*additionalConfig) + if err != nil { + panic(err) + } + iniConf.Parse(args) + + // Instantiate Tools + usr, _ := user.Current() + directory := filepath.Join(usr.HomeDir, ".arduino-create") + Tools = tools.Tools{ + Directory: directory, + IndexURL: *indexURL, + Logger: func(msg string) { + mapD := map[string]string{"DownloadStatus": "Pending", "Msg": msg} + mapB, _ := json.Marshal(mapD) + h.broadcastSys <- mapB + }, + } + Tools.Init(requiredToolsAPILevel) + + log.SetLevel(log.InfoLevel) + + log.SetOutput(os.Stderr) + + // see if we are supposed to wait 5 seconds + if *isLaunchSelf { + launchSelfLater() + } + + log.Println("Version:" + version) + + // hostname + hn, _ := os.Hostname() + if *hostname == "unknown-hostname" { + *hostname = hn + } + log.Println("Hostname:", *hostname) + + // turn off garbage collection + // this is dangerous, as u could overflow memory + //if *isGC { + if *gcType == "std" { + log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.") + } else if *gcType == "max" { + log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.") + } else { + log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.") + debug.SetGCPercent(-1) + } + + // see if they provided a regex filter + if len(*regExpFilter) > 0 { + log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter) + } + + // list serial ports + portList, _ := GetList(false) + log.Println("Your serial ports:") + if len(portList) == 0 { + log.Println("\tThere are no serial ports to list.") + } + for _, element := range portList { + log.Printf("\t%v\n", element) + + } + + if !*verbose { + log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.") + log.SetOutput(new(NullWriter)) //route all logging to nullwriter + } + + // launch the hub routine which is the singleton for the websocket server + go h.run() + // launch our serial port routine + go sh.run() + // launch our dummy data routine + //go d.run() + + go discoverLoop() + + r := gin.New() + + socketHandler := wsHandler().ServeHTTP + + extraOrigins := []string{ + "https://create.arduino.cc", + "http://create.arduino.cc", "https://create-dev.arduino.cc", "http://create-dev.arduino.cc", "https://create-intel.arduino.cc", "http://create-intel.arduino.cc", + } + + for i := 8990; i < 9001; i++ { + port := strconv.Itoa(i) + extraOrigins = append(extraOrigins, "http://localhost:"+port) + extraOrigins = append(extraOrigins, "https://localhost:"+port) + extraOrigins = append(extraOrigins, "http://127.0.0.1:"+port) + } + + r.Use(cors.Middleware(cors.Config{ + Origins: *origins + ", " + strings.Join(extraOrigins, ", "), + Methods: "GET, PUT, POST, DELETE", + RequestHeaders: "Origin, Authorization, Content-Type", + ExposedHeaders: "", + MaxAge: 50 * time.Second, + Credentials: true, + ValidateHeaders: false, + })) + + r.LoadHTMLFiles("templates/nofirefox.html") + + r.GET("/", homeHandler) + r.GET("/certificate.crt", certHandler) + r.DELETE("/certificate.crt", deleteCertHandler) + r.POST("/upload", uploadHandler) + r.GET("/socket.io/", socketHandler) + r.POST("/socket.io/", socketHandler) + r.Handle("WS", "/socket.io/", socketHandler) + r.Handle("WSS", "/socket.io/", socketHandler) + r.GET("/info", infoHandler) + r.POST("/killbrowser", killBrowserHandler) + r.POST("/pause", pauseHandler) + r.POST("/update", updateHandler) go func() { - - // autoextract self - src, _ := osext.Executable() - dest := filepath.Dir(src) - - // Instantiate Tools - usr, _ := user.Current() - directory := filepath.Join(usr.HomeDir, ".arduino-create") - Tools = tools.Tools{ - Directory: directory, - IndexURL: *indexURL, - Logger: func(msg string) { - mapD := map[string]string{"DownloadStatus": "Pending", "Msg": msg} - mapB, _ := json.Marshal(mapD) - h.broadcastSys <- mapB - }, + // check if certificates exist; if not, use plain http + if _, err := os.Stat(filepath.Join(dest, "cert.pem")); os.IsNotExist(err) { + return } - Tools.Init(requiredToolsAPILevel) - - if embedded_autoextract { - // save the config.ini (if it exists) - if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) { - log.Println("First run, unzipping self") - err := utilities.Unzip(src, dest) - log.Println("Self extraction, err:", err) - } - if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) { - flag.Parse() - log.Println("No config.ini at", *configIni) + start := 8990 + end := 9000 + i := start + for i < end { + i = i + 1 + portSSL = ":" + strconv.Itoa(i) + if err := r.RunTLS(*address+portSSL, filepath.Join(dest, "cert.pem"), filepath.Join(dest, "key.pem")); err != nil { + log.Printf("Error trying to bind to port: %v, so exiting...", err) + continue } else { - flag.Parse() - flag.Set("config", dest+"/"+*configIni) - iniflags.Parse() + log.Print("Starting server and websocket (SSL) on " + *address + "" + port) + break } - } else { - flag.Set("config", dest+"/"+*configIni) - iniflags.Parse() - } - - log.SetLevel(log.InfoLevel) - - log.SetOutput(os.Stderr) - - // see if we are supposed to wait 5 seconds - if *isLaunchSelf { - launchSelfLater() - } - - log.Println("Version:" + version) - - // hostname - hn, _ := os.Hostname() - if *hostname == "unknown-hostname" { - *hostname = hn - } - log.Println("Hostname:", *hostname) - - // turn off garbage collection - // this is dangerous, as u could overflow memory - //if *isGC { - if *gcType == "std" { - log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.") - } else if *gcType == "max" { - log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.") - } else { - log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.") - debug.SetGCPercent(-1) - } - - // see if they provided a regex filter - if len(*regExpFilter) > 0 { - log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter) } + }() - // list serial ports - portList, _ := GetList(false) - log.Println("Your serial ports:") - if len(portList) == 0 { - log.Println("\tThere are no serial ports to list.") - } - for _, element := range portList { - log.Printf("\t%v\n", element) - - } - - if !*verbose { - log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.") - log.SetOutput(new(NullWriter)) //route all logging to nullwriter - } - - // launch the hub routine which is the singleton for the websocket server - go h.run() - // launch our serial port routine - go sh.run() - // launch our dummy data routine - //go d.run() - - go discoverLoop() - - r := gin.New() - - socketHandler := wsHandler().ServeHTTP - - extraOrigins := []string{ - "https://create.arduino.cc", - "http://create.arduino.cc", "https://create-dev.arduino.cc", "http://create-dev.arduino.cc", "https://create-intel.arduino.cc", "http://create-intel.arduino.cc", - } - - for i := 8990; i < 9001; i++ { - port := strconv.Itoa(i) - extraOrigins = append(extraOrigins, "http://localhost:"+port) - extraOrigins = append(extraOrigins, "https://localhost:"+port) - extraOrigins = append(extraOrigins, "http://127.0.0.1:"+port) - } - - r.Use(cors.Middleware(cors.Config{ - Origins: *origins + ", " + strings.Join(extraOrigins, ", "), - Methods: "GET, PUT, POST, DELETE", - RequestHeaders: "Origin, Authorization, Content-Type", - ExposedHeaders: "", - MaxAge: 50 * time.Second, - Credentials: true, - ValidateHeaders: false, - })) - - r.LoadHTMLFiles("templates/nofirefox.html") - - r.GET("/", homeHandler) - r.GET("/certificate.crt", certHandler) - r.DELETE("/certificate.crt", deleteCertHandler) - r.POST("/upload", uploadHandler) - r.GET("/socket.io/", socketHandler) - r.POST("/socket.io/", socketHandler) - r.Handle("WS", "/socket.io/", socketHandler) - r.Handle("WSS", "/socket.io/", socketHandler) - r.GET("/info", infoHandler) - r.POST("/killbrowser", killBrowserHandler) - r.POST("/pause", pauseHandler) - r.POST("/update", updateHandler) - - go func() { - // check if certificates exist; if not, use plain http - if _, err := os.Stat(filepath.Join(dest, "cert.pem")); os.IsNotExist(err) { - return - } - - start := 8990 - end := 9000 - i := start - for i < end { - i = i + 1 - portSSL = ":" + strconv.Itoa(i) - if err := r.RunTLS(*address+portSSL, filepath.Join(dest, "cert.pem"), filepath.Join(dest, "key.pem")); err != nil { - log.Printf("Error trying to bind to port: %v, so exiting...", err) - continue - } else { - log.Print("Starting server and websocket (SSL) on " + *address + "" + port) - break - } - } - }() - - go func() { - start := 8990 - end := 9000 - i := start - for i < end { - i = i + 1 - port = ":" + strconv.Itoa(i) - if err := r.Run(*address + port); err != nil { - log.Printf("Error trying to bind to port: %v, so exiting...", err) - continue - } else { - log.Print("Starting server and websocket on " + *address + "" + port) - break - } + go func() { + start := 8990 + end := 9000 + i := start + for i < end { + i = i + 1 + port = ":" + strconv.Itoa(i) + if err := r.Run(*address + port); err != nil { + log.Printf("Error trying to bind to port: %v, so exiting...", err) + continue + } else { + log.Print("Starting server and websocket on " + *address + "" + port) + break } - }() - + } }() } setupSysTray() @@ -432,3 +451,26 @@ body { ` + +func parseIni(filename string) (args []string, err error) { + cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: false}, filename) + + if err != nil { + return nil, err + } + + for _, section := range cfg.Sections() { + for key, val := range section.KeysHash() { + // Ignore launchself + if key == "ls" { + continue + } // Ignore configUpdateInterval + if key == "configUpdateInterval" { + continue + } + args = append(args, "-"+key, val) + } + } + + return args, nil +} diff --git a/trayicon.go b/trayicon.go index 533487623..7db774c38 100644 --- a/trayicon.go +++ b/trayicon.go @@ -31,7 +31,6 @@ package main import ( - "flag" "os" "path/filepath" "runtime" @@ -42,7 +41,6 @@ import ( "github.com/go-ini/ini" "github.com/kardianos/osext" "github.com/skratchdot/open-golang/open" - "github.com/vharitonsky/iniflags" "go.bug.st/serial.v1" ) @@ -133,7 +131,7 @@ func setupSysTrayReal() { mConfigCheckbox = append(mConfigCheckbox, entry) // decorate configs gliph := " ☐ " - if *configIni == config.Localtion { + if *additionalConfig == config.Localtion { gliph = " 🗹 " } entry.SetTitle(gliph + config.Name) @@ -150,16 +148,8 @@ func setupSysTrayReal() { go func(v int) { for { <-mConfigCheckbox[v].ClickedCh - flag.Set("config", configs[v].Localtion) - iniflags.UpdateConfig() - applyEnvironment(configs[v].Localtion) - mConfigCheckbox[v].SetTitle(" 🗹 " + configs[v].Name) - //mConfigCheckbox[v].Check() - for j, _ := range mConfigCheckbox { - if j != v { - mConfigCheckbox[j].SetTitle(" ☐ " + configs[j].Name) - } - } + + restart("", "-additional-config", configs[v].Localtion) } }(i) } diff --git a/vendor/github.com/vharitonsky/iniflags/LICENSE b/vendor/github.com/vharitonsky/iniflags/LICENSE deleted file mode 100644 index 1d12d1626..000000000 --- a/vendor/github.com/vharitonsky/iniflags/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2014 vharitonsky, valyala. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. diff --git a/vendor/github.com/vharitonsky/iniflags/README.md b/vendor/github.com/vharitonsky/iniflags/README.md deleted file mode 100644 index f0138eba2..000000000 --- a/vendor/github.com/vharitonsky/iniflags/README.md +++ /dev/null @@ -1,141 +0,0 @@ -Hybrid configuration library -============================ - -Combine standard go flags with ini files. - -Usage: - -```bash - -go get -u -a github.com/vharitonsky/iniflags -``` - -main.go -```go -package main - -import ( - "flag" - ... - "github.com/vharitonsky/iniflags" - ... -) - -var ( - flag1 = flag.String("flag1", "default1", "Description1") - ... - flagN = flag.Int("flagN", 123, "DescriptionN") -) - -func main() { - iniflags.Parse() // use instead of flag.Parse() -} -``` - -dev.ini - -```ini - # comment1 - flag1 = "val1" # comment2 - - ... - [section] - flagN = 4 # comment3 -``` - -```bash - -go run main.go -config dev.ini -flagX=foobar - -``` - -Now all unset flags obtain their value from .ini file provided in -config path. -If value is not found in the .ini, flag will retain its' default value. - -Flag value priority: - - value set via command-line - - value from ini file - - default value - -Iniflags is compatible with real .ini config files with [sections] and #comments. -Sections and comments are skipped during config file parsing. - -Iniflags can #import another ini files. For example, - -base.ini -```ini -flag1 = value1 -flag2 = value2 -``` - -dev.ini -```ini -#import "base.ini" -# Now flag1="value1", flag2="value2" - -flag2 = foobar -# Now flag1="value1", while flag2="foobar" -``` - -Both -config path and imported ini files can be addressed via http -or https links: - -```bash -/path/to/app -config=https://google.com/path/to/config.ini -``` - -config.ini -```ini -# The following line will import configs from the given http link. -#import "http://google.com/path/to/config.ini" -``` - -All flags defined in the app can be dumped into stdout with ini-compatible sytax -by passing -dumpflags flag to the app. The following command creates ini-file -with all the flags defined in the app: - -```bash -/path/to/the/app -dumpflags > initial-config.ini -``` - - -Iniflags also supports two types of online config reload: - - * Via SIGHUP signal: - -```bash -kill -s SIGHUP -``` - - * Via -configUpdateInterval flag. The following line will re-read config every 5 seconds: - -```bash -/path/to/app -config=/path/to/config.ini -configUpdateInterval=5s -``` - - -Advanced usage. - -```go -package main - -import ( - "flag" - "iniflags" - "log" -) - -var listenPort = flag.Int("listenPort", 1234, "Port to listen to") - -func init() { - iniflags.OnFlagChange("listenPort", func() { - startServerOnPort(*listenPort) - }) -} - -func main() { - // iniflags.Parse() starts the server on the -listenPort via OnFlagChange() - // callback registered above. - iniflags.Parse() -} -``` diff --git a/vendor/github.com/vharitonsky/iniflags/iniflags.go b/vendor/github.com/vharitonsky/iniflags/iniflags.go deleted file mode 100644 index 0933a6b85..000000000 --- a/vendor/github.com/vharitonsky/iniflags/iniflags.go +++ /dev/null @@ -1,409 +0,0 @@ -package iniflags - -import ( - "bufio" - "flag" - "fmt" - "io" - "log" - "net/http" - "net/url" - "os" - "os/signal" - "path" - "strings" - "syscall" - "time" -) - -var ( - config = flag.String("config", "", "Path to ini config for using in go flags. May be relative to the current executable path.") - configUpdateInterval = flag.Duration("configUpdateInterval", 0, "Update interval for re-reading config file set via -config flag. Zero disables config file re-reading.") - dumpflags = flag.Bool("dumpflags", false, "Dumps values for all flags defined in the app into stdout in ini-compatible syntax and terminates the app.") -) - -var ( - flagChangeCallbacks = make(map[string][]FlagChangeCallback) - importStack []string - parsed bool -) - -// Generation is flags' generation number. -// -// It is modified on each flags' modification -// via either -configUpdateInterval or SIGHUP. -var Generation int - -// Parse obtains flag values from config file set via -config. -// -// It obtains flag values from command line like flag.Parse(), then overrides -// them by values parsed from config file set via -config. -// -// Path to config file can also be set via SetConfigFile() before Parse() call. -func Parse() { - if parsed { - panic("iniflags: duplicate call to iniflags.Parse() detected") - } - - parsed = true - flag.Parse() - _, ok := parseConfigFlags() - if !ok { - os.Exit(1) - } - - if *dumpflags { - dumpFlags() - os.Exit(0) - } - - for flagName := range flagChangeCallbacks { - verifyFlagChangeFlagName(flagName) - } - Generation++ - issueAllFlagChangeCallbacks() - - ch := make(chan os.Signal) - signal.Notify(ch, syscall.SIGHUP) - go sighupHandler(ch) - - go configUpdater() -} - -func configUpdater() { - if *configUpdateInterval != 0 { - for { - // Use time.Sleep() instead of time.Tick() for the sake of dynamic flag update. - time.Sleep(*configUpdateInterval) - UpdateConfig() - } - } -} - -func UpdateConfig() { - if oldFlagValues, ok := parseConfigFlags(); ok && len(oldFlagValues) > 0 { - modifiedFlags := make(map[string]string) - for k := range oldFlagValues { - modifiedFlags[k] = flag.Lookup(k).Value.String() - } - log.Printf("iniflags: read updated config. Modified flags are: %v\n", modifiedFlags) - Generation++ - issueFlagChangeCallbacks(oldFlagValues) - } -} - -// FlagChangeCallback is called when the given flag is changed. -// -// The callback may be registered for any flag via OnFlagChange(). -type FlagChangeCallback func() - -// OnFlagChange registers the callback, which is called after the given flag -// value is initialized and/or changed. -// -// Flag values are initialized during iniflags.Parse() call. -// Flag value can be changed on config re-read after obtaining SIGHUP signal -// or if periodic config re-read is enabled with -configUpdateInterval flag. -// -// Note that flags set via command-line cannot be overriden via config file modifications. -func OnFlagChange(flagName string, callback FlagChangeCallback) { - if parsed { - verifyFlagChangeFlagName(flagName) - } - flagChangeCallbacks[flagName] = append(flagChangeCallbacks[flagName], callback) -} - -func verifyFlagChangeFlagName(flagName string) { - if flag.Lookup(flagName) == nil { - log.Fatalf("iniflags: cannot register FlagChangeCallback for non-existing flag [%s]\n", flagName) - } -} - -func issueFlagChangeCallbacks(oldFlagValues map[string]string) { - for flagName := range oldFlagValues { - if fs, ok := flagChangeCallbacks[flagName]; ok { - for _, f := range fs { - f() - } - } - } -} - -func issueAllFlagChangeCallbacks() { - for _, fs := range flagChangeCallbacks { - for _, f := range fs { - f() - } - } -} - -func sighupHandler(ch <-chan os.Signal) { - for _ = range ch { - UpdateConfig() - } -} - -func parseConfigFlags() (oldFlagValues map[string]string, ok bool) { - configPath := *config - if !strings.HasPrefix(configPath, "./") { - if configPath, ok = combinePath(os.Args[0], *config); !ok { - return nil, false - } - } - if configPath == "" { - return nil, true - } - parsedArgs, ok := getArgsFromConfig(configPath) - if !ok { - return nil, false - } - missingFlags := getMissingFlags() - - ok = true - oldFlagValues = make(map[string]string) - for _, arg := range parsedArgs { - f := flag.Lookup(arg.Key) - if f == nil { - log.Printf("iniflags: unknown flag name=[%s] found at line [%d] of file [%s]\n", arg.Key, arg.LineNum, arg.FilePath) - ok = false - continue - } - - if _, found := missingFlags[f.Name]; found { - oldValue := f.Value.String() - if oldValue == arg.Value { - continue - } - if err := f.Value.Set(arg.Value); err != nil { - log.Printf("iniflags: error when parsing flag [%s] value [%s] at line [%d] of file [%s]: [%s]\n", arg.Key, arg.Value, arg.LineNum, arg.FilePath, err) - ok = false - continue - } - if oldValue != f.Value.String() { - oldFlagValues[arg.Key] = oldValue - } - } - } - - if !ok { - // restore old flag values - for k, v := range oldFlagValues { - flag.Set(k, v) - } - oldFlagValues = nil - } - - return oldFlagValues, ok -} - -func checkImportRecursion(configPath string) bool { - for _, path := range importStack { - if path == configPath { - log.Printf("iniflags: import recursion found for [%s]: %v\n", configPath, importStack) - return false - } - } - return true -} - -type flagArg struct { - Key string - Value string - FilePath string - LineNum int -} - -func stripBOM(s string) string { - if len(s) < 3 { - return s - } - bom := s[:3] - if bom == "\ufeff" || bom == "\ufffe" { - return s[3:] - } - return s -} - -func getArgsFromConfig(configPath string) (args []flagArg, ok bool) { - if !checkImportRecursion(configPath) { - return nil, false - } - importStack = append(importStack, configPath) - defer func() { - importStack = importStack[:len(importStack)-1] - }() - - file := openConfigFile(configPath) - if file == nil { - return nil, false - } - defer file.Close() - r := bufio.NewReader(file) - - var lineNum int - for { - lineNum++ - line, err := r.ReadString('\n') - if err != nil && line == "" { - if err == io.EOF { - break - } - log.Printf("iniflags: error when reading file [%s] at line %d: [%s]\n", configPath, lineNum, err) - return nil, false - } - if lineNum == 1 { - line = stripBOM(line) - } - line = strings.TrimSpace(line) - if strings.HasPrefix(line, "#import ") { - importPath, ok := unquoteValue(line[7:], lineNum, configPath) - if !ok { - return nil, false - } - if importPath, ok = combinePath(configPath, importPath); !ok { - return nil, false - } - importArgs, ok := getArgsFromConfig(importPath) - if !ok { - return nil, false - } - args = append(args, importArgs...) - continue - } - if line == "" || line[0] == ';' || line[0] == '#' || line[0] == '[' { - continue - } - parts := strings.SplitN(line, "=", 2) - if len(parts) != 2 { - log.Printf("iniflags: cannot split [%s] at line %d into key and value in config file [%s]\n", line, lineNum, configPath) - return nil, false - } - key := strings.TrimSpace(parts[0]) - value, ok := unquoteValue(parts[1], lineNum, configPath) - if !ok { - return nil, false - } - args = append(args, flagArg{Key: key, Value: value, FilePath: configPath, LineNum: lineNum}) - } - - return args, true -} - -func openConfigFile(path string) io.ReadCloser { - if isHTTP(path) { - resp, err := http.Get(path) - if err != nil { - log.Printf("iniflags: cannot load config file at [%s]: [%s]\n", path, err) - return nil - } - if resp.StatusCode != http.StatusOK { - log.Printf("iniflags: unexpected http status code when obtaining config file [%s]: %d. Expected %d\n", path, resp.StatusCode, http.StatusOK) - return nil - } - return resp.Body - } - - file, err := os.Open(path) - if err != nil { - log.Printf("iniflags: cannot open config file at [%s]: [%s]\n", path, err) - return nil - } - return file -} - -func combinePath(basePath, relPath string) (string, bool) { - if isHTTP(basePath) { - base, err := url.Parse(basePath) - if err != nil { - log.Printf("iniflags: error when parsing http base path [%s]: %s\n", basePath, err) - return "", false - } - rel, err := url.Parse(relPath) - if err != nil { - log.Printf("iniflags: error when parsing http rel path [%s] for base [%s]: %s\n", relPath, basePath, err) - return "", false - } - return base.ResolveReference(rel).String(), true - } - - if relPath == "" || relPath[0] == '/' || isHTTP(relPath) { - return relPath, true - } - return path.Join(path.Dir(basePath), relPath), true -} - -func isHTTP(path string) bool { - return strings.HasPrefix(strings.ToLower(path), "http://") || strings.HasPrefix(strings.ToLower(path), "https://") -} - -func getMissingFlags() map[string]bool { - setFlags := make(map[string]bool) - flag.Visit(func(f *flag.Flag) { - setFlags[f.Name] = true - }) - - missingFlags := make(map[string]bool) - flag.VisitAll(func(f *flag.Flag) { - if _, ok := setFlags[f.Name]; !ok { - missingFlags[f.Name] = true - } - }) - return missingFlags -} - -func dumpFlags() { - flag.VisitAll(func(f *flag.Flag) { - if f.Name != "config" && f.Name != "dumpflags" { - fmt.Printf("%s = %s # %s\n", f.Name, quoteValue(f.Value.String()), escapeUsage(f.Usage)) - } - }) -} - -func escapeUsage(s string) string { - return strings.Replace(s, "\n", "\n # ", -1) -} - -func quoteValue(v string) string { - if !strings.ContainsAny(v, "\n#;") && strings.TrimSpace(v) == v { - return v - } - v = strings.Replace(v, "\\", "\\\\", -1) - v = strings.Replace(v, "\n", "\\n", -1) - v = strings.Replace(v, "\"", "\\\"", -1) - return fmt.Sprintf("\"%s\"", v) -} - -func unquoteValue(v string, lineNum int, configPath string) (string, bool) { - v = strings.TrimSpace(v) - if len(v) == 0 { - return "", true - } - if v[0] != '"' { - return removeTrailingComments(v), true - } - n := strings.LastIndex(v, "\"") - if n == -1 { - log.Printf("iniflags: unclosed string found [%s] at line %d in config file [%s]\n", v, lineNum, configPath) - return "", false - } - v = v[1:n] - v = strings.Replace(v, "\\\"", "\"", -1) - v = strings.Replace(v, "\\n", "\n", -1) - return strings.Replace(v, "\\\\", "\\", -1), true -} - -func removeTrailingComments(v string) string { - v = strings.Split(v, "#")[0] - v = strings.Split(v, ";")[0] - return strings.TrimSpace(v) -} - -// SetConfigFile sets path to config file. -// -// Call this function before Parse() if you need default path to config file -// when -config command-line flag is not set. -func SetConfigFile(path string) { - if parsed { - panic("iniflags: SetConfigFile() must be called before Parse()") - } - *config = path -} diff --git a/vendor/github.com/vharitonsky/iniflags/test_bom.ini b/vendor/github.com/vharitonsky/iniflags/test_bom.ini deleted file mode 100644 index 468e8d394..000000000 --- a/vendor/github.com/vharitonsky/iniflags/test_bom.ini +++ /dev/null @@ -1 +0,0 @@ -bom=привет diff --git a/vendor/github.com/vharitonsky/iniflags/test_config.ini b/vendor/github.com/vharitonsky/iniflags/test_config.ini deleted file mode 100644 index 052c4665a..000000000 --- a/vendor/github.com/vharitonsky/iniflags/test_config.ini +++ /dev/null @@ -1,8 +0,0 @@ -# comment -var0 = val0 ; comment - -[section] -#import "test_config2.ini" # import another config - var1 = "val#1\n\\\"\nx" # this is a test comment - -var3 = # empty value diff --git a/vendor/github.com/vharitonsky/iniflags/test_config2.ini b/vendor/github.com/vharitonsky/iniflags/test_config2.ini deleted file mode 100644 index 00c1f0711..000000000 --- a/vendor/github.com/vharitonsky/iniflags/test_config2.ini +++ /dev/null @@ -1,3 +0,0 @@ - -; this file is imported from test_config.ini -var2 = 1234 # comment diff --git a/vendor/github.com/vharitonsky/iniflags/test_setconfigfile.ini b/vendor/github.com/vharitonsky/iniflags/test_setconfigfile.ini deleted file mode 100644 index 3369c8227..000000000 --- a/vendor/github.com/vharitonsky/iniflags/test_setconfigfile.ini +++ /dev/null @@ -1 +0,0 @@ -x = foobar diff --git a/vendor/vendor.json b/vendor/vendor.json index 1adb11a7f..f448a0901 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -206,11 +206,6 @@ "revision": "c8748311a7528d0ba7330d302adbc5a677ef9c9e", "revisionTime": "2015-02-21T09:03:35-05:00" }, - { - "path": "github.com/vharitonsky/iniflags", - "revision": "02b57ef987a5ee59eedc7dcd93315a43f6dcc4a7", - "revisionTime": "2015-11-14T13:23:54+02:00" - }, { "path": "github.com/xrash/smetrics", "revision": "81a89232431423f9140fa413823ce3045f02f19c", From c774ab79d716a28fda48550540d20d0ffcf55872 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Wed, 25 Jul 2018 14:14:06 +0200 Subject: [PATCH 2/4] Fix config.ini --- config.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.ini b/config.ini index 3c4348aa2..1f9df1eea 100644 --- a/config.ini +++ b/config.ini @@ -4,4 +4,4 @@ regex = usb|acm|com # Regular expression to filter serial port list v = true # show debug logging appName = CreateBridge updateUrl = http://downloads.arduino.cc/ -origins = http://downloads.arduino.cc/ +origins = http://local.arduino.cc:8000 From 7d4794bde728e384284923de5c430207fc6020e0 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Wed, 25 Jul 2018 14:17:09 +0200 Subject: [PATCH 3/4] ignore main in ini --- main.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 3fdc8177e..3f0614a47 100755 --- a/main.go +++ b/main.go @@ -116,7 +116,6 @@ func main() { // Parse ini config args, err := parseIni("config.ini") - fmt.Println(args) if err != nil { panic(err) } @@ -130,7 +129,10 @@ func main() { if err != nil { panic(err) } - iniConf.Parse(args) + err = iniConf.Parse(args) + if err != nil { + panic(err) + } // Instantiate Tools usr, _ := user.Current() @@ -454,7 +456,6 @@ body { func parseIni(filename string) (args []string, err error) { cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: false}, filename) - if err != nil { return nil, err } @@ -467,6 +468,9 @@ func parseIni(filename string) (args []string, err error) { } // Ignore configUpdateInterval if key == "configUpdateInterval" { continue + } // Ignore name + if key == "name" { + continue } args = append(args, "-"+key, val) } From f24d15ff58d8c3d6788890b500d7b6dda5f1ecc7 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Wed, 25 Jul 2018 14:18:26 +0200 Subject: [PATCH 4/4] Remove dead code --- trayicon.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/trayicon.go b/trayicon.go index 7db774c38..5f9e3dfd7 100644 --- a/trayicon.go +++ b/trayicon.go @@ -99,21 +99,6 @@ func getConfigs() []ConfigIni { return configs } -func applyEnvironment(filename string) { - src, _ := osext.Executable() - dest := filepath.Dir(src) - cfg, _ := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, filepath.Join(dest, filename)) - defaultSection, err := cfg.GetSection("env") - if err != nil { - return - } - for _, env := range defaultSection.KeyStrings() { - val := defaultSection.Key(env).String() - log.Info("Applying env setting: " + env + "=" + val) - os.Setenv(env, val) - } -} - func setupSysTrayReal() { systray.SetIcon(icon.GetIcon()) @@ -136,9 +121,6 @@ func setupSysTrayReal() { } entry.SetTitle(gliph + config.Name) } - } else { - // apply env setting from first config immediately - // applyEnvironment(configs[0].Localtion) } //mQuit := systray.AddMenuItem("Quit Plugin", "")