From 8975be2026bcbe84dc1392f917151a086033a2a8 Mon Sep 17 00:00:00 2001 From: Ad van der Veer Date: Sun, 17 May 2015 09:24:03 +0200 Subject: [PATCH 1/5] started on version 0.4 [6m0s] --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9e11b32..1d0ba9e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.1 +0.4.0 From c434c64a584ec19a48a91d538a717aa321749402 Mon Sep 17 00:00:00 2001 From: Ad van der Veer Date: Sun, 17 May 2015 10:14:40 +0200 Subject: [PATCH 2/5] daemon requests version and cli keeps it in memory [] --- command/client.go | 14 ++++++++----- command/status.go | 2 +- daemon/main.go | 3 +++ daemon/server.go | 53 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/command/client.go b/command/client.go index f0d1767..e8f5f06 100644 --- a/command/client.go +++ b/command/client.go @@ -20,11 +20,17 @@ type Client struct { *http.Client } +type StatusData struct { + Time string + MostRecentVersion string + CurrentVersion string +} + func NewClient(info *model.Daemon) *Client { return &Client{ info: info, Client: &http.Client{ - Timeout: time.Duration(100 * time.Millisecond), + Timeout: time.Duration(400 * time.Millisecond), }, } } @@ -67,7 +73,7 @@ func (c *Client) Lap() (time.Duration, error) { return d, nil } -func (c *Client) Split() (time.Duration, error) { +func (c *Client) GetStatus() (time.Duration, error) { resp, err := c.Get(fmt.Sprintf("http://%s/timer.status", c.info.Addr)) if err != nil { return 0, ErrDaemonDown @@ -77,9 +83,7 @@ func (c *Client) Split() (time.Duration, error) { dec := json.NewDecoder(resp.Body) defer resp.Body.Close() - status := struct { - Time string - }{} + status := &StatusData{} err = dec.Decode(&status) if err != nil { diff --git a/command/status.go b/command/status.go index 6e40348..6c91306 100644 --- a/command/status.go +++ b/command/status.go @@ -51,7 +51,7 @@ func (c *Status) Run(ctx *cli.Context) error { } client := NewClient(info) - t, err := client.Split() + t, err := client.GetStatus() if err != nil { if err == ErrDaemonDown { return errwrap.Wrapf(fmt.Sprintf("No timer appears to be running for '%s': {{err}}", dir), err) diff --git a/daemon/main.go b/daemon/main.go index a26c29c..df70c4b 100644 --- a/daemon/main.go +++ b/daemon/main.go @@ -33,6 +33,9 @@ func main() { log.Fatal(err) } + //check version without delaying start times + go svr.CheckVersion() + dir, err := os.Getwd() if err != nil { log.Fatal(errwrap.Wrapf("Failed to fetch current working dir: {{err}}", err)) diff --git a/daemon/server.go b/daemon/server.go index d6f0622..1842e3b 100644 --- a/daemon/server.go +++ b/daemon/server.go @@ -1,19 +1,26 @@ package main import ( + "bytes" "fmt" + "io" + "log" "net" "net/http" + "strings" "github.com/hashicorp/errwrap" "github.com/labstack/echo" ) +var CheckVersionURL = "https://s3-eu-west-1.amazonaws.com/timeglass/version/VERSION" + type Server struct { - timer *Timer - httpb string - router *echo.Echo - listener net.Listener + timer *Timer + httpb string + router *echo.Echo + listener net.Listener + mostRecentVersion string *http.Server } @@ -41,9 +48,16 @@ func (s *Server) lap(c *echo.Context) *echo.HTTPError { } func (s *Server) status(c *echo.Context) *echo.HTTPError { - return c.JSON(http.StatusOK, map[string]interface{}{ - "Time": s.timer.Time().String(), - }) + data := map[string]interface{}{ + "CurrentVersion": Version, + "MostRecentVersion": s.mostRecentVersion, + "Time": s.timer.Time().String(), + } + + //check version without delaying response + go s.CheckVersion() + + return c.JSON(http.StatusOK, data) } func version(c *echo.Context) *echo.HTTPError { @@ -58,11 +72,12 @@ func NewServer(httpb string, timer *Timer) (*Server, error) { } s := &Server{ - timer: timer, - httpb: httpb, - router: router, - listener: l, - Server: &http.Server{Handler: router}, + timer: timer, + httpb: httpb, + router: router, + listener: l, + mostRecentVersion: Version, + Server: &http.Server{Handler: router}, } router.Get("/", version) @@ -87,3 +102,17 @@ func (s *Server) Start() error { s.timer.Start() return s.Server.Serve(s.listener) } + +func (s *Server) CheckVersion() { + resp, err := http.Get(CheckVersionURL) + if err == nil { + defer resp.Body.Close() + buff := bytes.NewBuffer(nil) + _, err = io.Copy(buff, resp.Body) + if err != nil { + log.Printf("Failed to read response body for version check: %s", err) + } else { + s.mostRecentVersion = strings.TrimSpace(buff.String()) + } + } +} From 041e5e1bc4a28143546548c444313879e125de5f Mon Sep 17 00:00:00 2001 From: Ad van der Veer Date: Sun, 17 May 2015 10:29:01 +0200 Subject: [PATCH 3/5] cli now shows if new version is available [15m0s] --- command/client.go | 15 +++++---------- command/status.go | 25 +++++++++++++++++++++++-- vcs/git.go | 2 +- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/command/client.go b/command/client.go index e8f5f06..eb5a0ba 100644 --- a/command/client.go +++ b/command/client.go @@ -73,12 +73,12 @@ func (c *Client) Lap() (time.Duration, error) { return d, nil } -func (c *Client) GetStatus() (time.Duration, error) { +func (c *Client) GetStatus() (*StatusData, error) { resp, err := c.Get(fmt.Sprintf("http://%s/timer.status", c.info.Addr)) if err != nil { - return 0, ErrDaemonDown + return nil, ErrDaemonDown } else if resp.StatusCode != 200 { - return 0, fmt.Errorf("Unexpected StatusCode from Daemon: %d", resp.StatusCode) + return nil, fmt.Errorf("Unexpected StatusCode from Daemon: %d", resp.StatusCode) } dec := json.NewDecoder(resp.Body) @@ -87,13 +87,8 @@ func (c *Client) GetStatus() (time.Duration, error) { err = dec.Decode(&status) if err != nil { - return 0, errwrap.Wrapf("Failed to decode json response: {{err}}", err) + return status, errwrap.Wrapf("Failed to decode json response: {{err}}", err) } - d, err := time.ParseDuration(status.Time) - if err != nil { - return 0, errwrap.Wrapf(fmt.Sprintf("Failed to parse '%s' as a time duration: {{err}}", status.Time), err) - } - - return d, nil + return status, nil } diff --git a/command/status.go b/command/status.go index 6c91306..c97b25d 100644 --- a/command/status.go +++ b/command/status.go @@ -3,6 +3,9 @@ package command import ( "fmt" "os" + "strconv" + "strings" + "time" "github.com/codegangsta/cli" "github.com/hashicorp/errwrap" @@ -31,7 +34,11 @@ func (c *Status) Usage() string { } func (c *Status) Flags() []cli.Flag { - return []cli.Flag{} + return []cli.Flag{ + cli.BoolFlag{ + Name: "time-only", + Usage: "Only display the time", + }} } func (c *Status) Action() func(ctx *cli.Context) { @@ -51,7 +58,7 @@ func (c *Status) Run(ctx *cli.Context) error { } client := NewClient(info) - t, err := client.GetStatus() + status, err := client.GetStatus() if err != nil { if err == ErrDaemonDown { return errwrap.Wrapf(fmt.Sprintf("No timer appears to be running for '%s': {{err}}", dir), err) @@ -60,6 +67,20 @@ func (c *Status) Run(ctx *cli.Context) error { } } + t, err := time.ParseDuration(status.Time) + if err != nil { + return errwrap.Wrapf(fmt.Sprintf("Failed to parse '%s' as a time duration: {{err}}", status.Time), err) + } + + //simple semver check + if !ctx.Bool("time-only") { + curr, _ := strconv.Atoi(strings.Replace("0.2.0", ".", "", 2)) + recent, _ := strconv.Atoi(strings.Replace(status.MostRecentVersion, ".", "", 2)) + if curr != 0 && recent > curr { + fmt.Println("A new version of Timeglass is available, please upgrade from https://github.com/timeglass/glass/releases.") + } + } + fmt.Println(t) return nil } diff --git a/vcs/git.go b/vcs/git.go index 9125d10..9d703de 100644 --- a/vcs/git.go +++ b/vcs/git.go @@ -21,7 +21,7 @@ var PrepCommitTmpl = template.Must(template.New("name").Parse(`#!/bin/sh # @see http://git-scm.com/docs/githooks#_prepare_commit_msg case "$2" in message|template) - printf "$(cat $1) [$(glass status)]" > "$1" ;; + printf "$(cat $1) [$(glass status --time-only)]" > "$1" ;; esac `)) From 93bfaa5c6640acfc033a0f01713f30fa90d31efc Mon Sep 17 00:00:00 2001 From: Ad van der Veer Date: Sun, 17 May 2015 10:29:38 +0200 Subject: [PATCH 4/5] now use actual value [0] --- command/status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/status.go b/command/status.go index c97b25d..d136024 100644 --- a/command/status.go +++ b/command/status.go @@ -74,7 +74,7 @@ func (c *Status) Run(ctx *cli.Context) error { //simple semver check if !ctx.Bool("time-only") { - curr, _ := strconv.Atoi(strings.Replace("0.2.0", ".", "", 2)) + curr, _ := strconv.Atoi(strings.Replace(status.CurrentVersion, ".", "", 2)) recent, _ := strconv.Atoi(strings.Replace(status.MostRecentVersion, ".", "", 2)) if curr != 0 && recent > curr { fmt.Println("A new version of Timeglass is available, please upgrade from https://github.com/timeglass/glass/releases.") From 1f784e9b373a5989a7cf202de7b550083d36a62e Mon Sep 17 00:00:00 2001 From: Ad van der Veer Date: Sun, 17 May 2015 10:45:49 +0200 Subject: [PATCH 5/5] no longer show empty brackets on empty time [15m0s] --- command/status.go | 10 +++++++++- vcs/git.go | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/command/status.go b/command/status.go index d136024..a6a7218 100644 --- a/command/status.go +++ b/command/status.go @@ -79,8 +79,16 @@ func (c *Status) Run(ctx *cli.Context) error { if curr != 0 && recent > curr { fmt.Println("A new version of Timeglass is available, please upgrade from https://github.com/timeglass/glass/releases.") } + } else if t.Seconds() == 0 { + //for script usage we return nothing when there has zero + //time elapsed, this prevents empty bracke + return nil + } + + fmt.Printf(" [%s]", t) + if !ctx.Bool("time-only") { + fmt.Println() } - fmt.Println(t) return nil } diff --git a/vcs/git.go b/vcs/git.go index 9d703de..5a309aa 100644 --- a/vcs/git.go +++ b/vcs/git.go @@ -21,7 +21,7 @@ var PrepCommitTmpl = template.Must(template.New("name").Parse(`#!/bin/sh # @see http://git-scm.com/docs/githooks#_prepare_commit_msg case "$2" in message|template) - printf "$(cat $1) [$(glass status --time-only)]" > "$1" ;; + printf "$(cat $1)$(glass status --time-only)" > "$1" ;; esac `))