Repository: gobuffalo/buffalo
Pull request #1309 (2018-09-19 15:06:48)

this re-brands refresh events as buffalo:dev events. it also fixes a data race found in context

codecov[bot]: # [Codecov](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=h1) Report
> Merging [#1309](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=desc) into [development](https://codecov.io/gh/gobuffalo/buffalo/commit/b9bf9618a707c0f098f2e8f17c4adbcc04ea3769?src=pr&el=desc) will **increase** coverage by `0.06%`.
> The diff coverage is `68.18%`.

[![Impacted file tree graph](https://codecov.io/gh/gobuffalo/buffalo/pull/1309/graphs/tree.svg?width=650&token=1Yyy8wHMMl&height=150&src=pr)](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=tree)

```diff
@@               Coverage Diff               @@
##           development    #1309      +/-   ##
===============================================
+ Coverage        53.85%   53.92%   +0.06%     
===============================================
  Files               76       76              
  Lines             3524     3540      +16     
===============================================
+ Hits              1898     1909      +11     
- Misses            1526     1530       +4     
- Partials           100      101       +1
```


| [Impacted Files](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [context.go](https://codecov.io/gh/gobuffalo/buffalo/pull/1309/diff?src=pr&el=tree#diff-Y29udGV4dC5nbw==) | `100% <100%> (ø)` | :arrow_up: |
| [buffalo/cmd/dev.go](https://codecov.io/gh/gobuffalo/buffalo/pull/1309/diff?src=pr&el=tree#diff-YnVmZmFsby9jbWQvZGV2Lmdv) | `5.55% <16.66%> (+0.79%)` | :arrow_up: |
| [default\_context.go](https://codecov.io/gh/gobuffalo/buffalo/pull/1309/diff?src=pr&el=tree#diff-ZGVmYXVsdF9jb250ZXh0Lmdv) | `68.53% <86.66%> (+2.11%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=footer). Last update [b9bf961...5547baa](https://codecov.io/gh/gobuffalo/buffalo/pull/1309?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/buffalo/cmd/dev.go b/buffalo/cmd/dev.go
index e38d2d8d..0402b9ff 100644
--- a/buffalo/cmd/dev.go
+++ b/buffalo/cmd/dev.go
@@ -6,11 +6,13 @@ import (
 	"os/exec"
 	"path/filepath"
 	"runtime"
+	"strings"
 
 	"github.com/fatih/color"
 	"github.com/gobuffalo/buffalo/generators/assets/webpack"
 	rg "github.com/gobuffalo/buffalo/generators/refresh"
 	"github.com/gobuffalo/buffalo/meta"
+	"github.com/gobuffalo/events"
 	"github.com/markbates/refresh/refresh"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -18,6 +20,15 @@ import (
 	"golang.org/x/sync/errgroup"
 )
 
+func init() {
+	events.NamedListen("buffalo:dev", func(e events.Event) {
+		if strings.HasPrefix(e.Kind, "refresh:") || strings.HasPrefix(e.Kind, "err:refresh:") {
+			e.Kind = strings.Replace(e.Kind, "refresh:", "buffalo:dev:", 1)
+			events.Emit(e)
+		}
+	})
+}
+
 var devOptions = struct {
 	Debug bool
 }{}
diff --git a/context.go b/context.go
index e2c0a78d..ffa7f869 100644
--- a/context.go
+++ b/context.go
@@ -3,6 +3,7 @@ package buffalo
 import (
 	"context"
 	"net/http"
+	"sync"
 
 	"github.com/gobuffalo/buffalo/binding"
 	"github.com/gobuffalo/buffalo/render"
@@ -87,5 +88,6 @@ func (a *App) newContext(info RouteInfo, res http.ResponseWriter, req *http.Requ
 		session:     session,
 		flash:       newFlash(session),
 		data:        contextData,
+		moot:        &sync.RWMutex{},
 	}
 }
diff --git a/default_context.go b/default_context.go
index 063452a6..12e9fa2d 100644
--- a/default_context.go
+++ b/default_context.go
@@ -11,6 +11,7 @@ import (
 	"reflect"
 	"sort"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/gobuffalo/buffalo/binding"
@@ -35,6 +36,7 @@ type DefaultContext struct {
 	contentType string
 	data        map[string]interface{}
 	flash       *Flash
+	moot        *sync.RWMutex
 }
 
 // Response returns the original Response for the request.
@@ -73,6 +75,8 @@ func (d *DefaultContext) Set(key string, value interface{}) {
 // Value that has previously stored on the context.
 func (d *DefaultContext) Value(key interface{}) interface{} {
 	if k, ok := key.(string); ok {
+		d.moot.RLock()
+		defer d.moot.RUnlock()
 		if v, ok := d.data[k]; ok {
 			return v
 		}
@@ -106,7 +110,7 @@ func (d *DefaultContext) Render(status int, rr render.Renderer) error {
 		d.LogField("render", time.Since(start))
 	}()
 	if rr != nil {
-		data := d.data
+		data := d.Data()
 		pp := map[string]string{}
 		for k, v := range d.params {
 			pp[k] = v[0]
@@ -213,13 +217,20 @@ func (d *DefaultContext) Redirect(status int, url string, args ...interface{}) e
 
 // Data contains all the values set through Get/Set.
 func (d *DefaultContext) Data() map[string]interface{} {
-	return d.data
+	m := map[string]interface{}{}
+	d.moot.RLock()
+	for k, v := range d.data {
+		m[k] = v
+	}
+	d.moot.RUnlock()
+	return m
 }
 
 func (d *DefaultContext) String() string {
-	bb := make([]string, 0, len(d.data))
+	data := d.Data()
+	bb := make([]string, 0, len(data))
 
-	for k, v := range d.data {
+	for k, v := range data {
 		if _, ok := v.(RouteHelperFunc); !ok {
 			bb = append(bb, fmt.Sprintf("%s: %s", k, v))
 		}
@@ -246,9 +257,9 @@ func (d *DefaultContext) File(name string) (binding.File, error) {
 }
 
 // MarshalJSON implements json marshaling for the context
-func (d DefaultContext) MarshalJSON() ([]byte, error) {
+func (d *DefaultContext) MarshalJSON() ([]byte, error) {
 	m := map[string]interface{}{}
-	for k, v := range d.data {
+	for k, v := range d.Data() {
 		if _, err := json.Marshal(v); err == nil {
 			// it can be marshaled, so add it:
 			m[k] = v
diff --git a/go.mod b/go.mod
index 9d4f9317..08770eaf 100644
--- a/go.mod
+++ b/go.mod
@@ -30,7 +30,7 @@ require (
 	github.com/markbates/deplist v1.0.3
 	github.com/markbates/grift v1.0.2
 	github.com/markbates/inflect v1.0.0
-	github.com/markbates/refresh v1.4.3
+	github.com/markbates/refresh v1.4.5
 	github.com/markbates/sigtx v1.0.0
 	github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba
 	github.com/pkg/errors v0.8.0
@@ -43,6 +43,5 @@ require (
 	golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b
 	golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
 	golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
-	google.golang.org/appengine v1.2.0 // indirect
 	gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4
 )
diff --git a/go.sum b/go.sum
index ed9b58ca..97480ce9 100644
--- a/go.sum
+++ b/go.sum
@@ -43,12 +43,14 @@ github.com/gobuffalo/genny v0.0.0-20180904214332-b7dcbfc7ea0a/go.mod h1:CX+ymPzT
 github.com/gobuffalo/genny v0.0.0-20180905180744-ca4140706556/go.mod h1:FZNXcfF+FuV4i8BANht5bghYawahu+sIrDdES9govgw=
 github.com/gobuffalo/genny v0.0.0-20180911182620-ca7c22ecfecc/go.mod h1:HbQtrpn9s0isId+tZMmU6Qssj5ag0Ce2Lj3qd3qBblE=
 github.com/gobuffalo/genny v0.0.0-20180911185118-5ca23a895a78/go.mod h1:e694VPwR0+kdvN8aSzC0T7+D6LwOs526YdZvAnw35Og=
+github.com/gobuffalo/genny v0.0.0-20180918201921-ac6244947a9a/go.mod h1:o0XtBk+olc3Kt5D6vld+XkKvUz3Y7t/SqcBNB2XB1lc=
 github.com/gobuffalo/github_flavored_markdown v1.0.0 h1:e2dK+SoHgOc/vfXuYMdXwEg2vAUlFzp8SBRwTOXckQ0=
 github.com/gobuffalo/github_flavored_markdown v1.0.0/go.mod h1:c8/8gRnd6MSyyk+fp6E8O8cUTHd7P2cnDnH4G7o91l0=
 github.com/gobuffalo/httptest v1.0.1 h1:F7KibLzHAHy1UZVpqwcd95aKcoI3gbSj7FgkDZ9lHow=
 github.com/gobuffalo/httptest v1.0.1/go.mod h1:ZLh197oiAQAJO2L7WYaZhllanqUUkWsUQ75bU6D1J6A=
 github.com/gobuffalo/licenser v0.0.0-20180911183003-6611b155b234/go.mod h1:dKS3aMBLM+AbeP4NdNL80CDl62D5aP/HmZ0Vwk72PLE=
 github.com/gobuffalo/makr v1.1.1/go.mod h1:1Ga9O4Gqd5xXc+AoI3eLwgu7k+gWamSUXd2Ps942KkM=
+github.com/gobuffalo/makr v1.1.2 h1:Dix34nvNM3v4EHNmoVysaAZBgPbMFJTwKXBrVonw2Kg=
 github.com/gobuffalo/makr v1.1.2/go.mod h1:5/uvRIyR+DQHJrX0UPCPF0WhQGMJG5/xd9XT9qEXQE8=
 github.com/gobuffalo/makr v1.1.5 h1:lOlpv2iz0dNa4qse0ZYQgbtT+ybwVxWEAcOZbcPmeYc=
 github.com/gobuffalo/makr v1.1.5/go.mod h1:Y+o0btAH1kYAMDJW/TX3+oAXEu0bmSLLoC9mIFxtzOw=
@@ -83,6 +85,7 @@ github.com/gobuffalo/release v1.0.7/go.mod h1:fJfvbgm624b3lCuMeK5w0E9t06dd4EHlUl
 github.com/gobuffalo/release v1.0.10/go.mod h1:HpNe26lUCPWdMOoQqGk5di5WOlDrcdPbqH2ZL/s2jD8=
 github.com/gobuffalo/release v1.0.11/go.mod h1:f8b4Cc2HaHNH1xCvRKPPK0aNt1wX/xxZkmV3/AdEu14=
 github.com/gobuffalo/release v1.0.15/go.mod h1:+o8sFaBFjjxCQiyo0S8bd7Tgv8t2pBrU12xd8bZQuBk=
+github.com/gobuffalo/release v1.0.17/go.mod h1:ZK/f7bzk4uxNEUnX9xOroXHhOA8bOg+2RuDjyUIuyUQ=
 github.com/gobuffalo/shoulders v0.0.0-20180904151418-9cac5899ceee/go.mod h1:atyzRdR+uoOgsuA3AL82yYx5yJ4vONfDYtQXZCuT9TI=
 github.com/gobuffalo/tags v2.0.6+incompatible/go.mod h1:9XmhOkyaB7UzvuY4UoZO4s67q8/xRMVJEaakauVQYeY=
 github.com/gobuffalo/tags v2.0.10+incompatible/go.mod h1:9XmhOkyaB7UzvuY4UoZO4s67q8/xRMVJEaakauVQYeY=
@@ -151,8 +154,9 @@ github.com/markbates/inflect v1.0.0/go.mod h1:oTeZL2KHA7CUX6X+fovmK9OvIOFuqu0Twd
 github.com/markbates/oncer v0.0.0-20180911182537-c659b9304060/go.mod h1:rwZBl6yM6wSTptDSNbV86jNkXmrr8TYPQ3/qwkrIkp0=
 github.com/markbates/oncer v0.0.0-20180911185008-7302a2cd9114/go.mod h1:rwZBl6yM6wSTptDSNbV86jNkXmrr8TYPQ3/qwkrIkp0=
 github.com/markbates/refresh v1.4.1/go.mod h1:og/05QDfszH/SCl3w8VI2Or990yna0wS2lqRcJoDqAg=
-github.com/markbates/refresh v1.4.3 h1:qeWHdyIRRImCeU5seAK0TQ+Tc9UtFA0wS5GfkmjC8W0=
 github.com/markbates/refresh v1.4.3/go.mod h1:C/Zey3IPrq0lXq1+SDhCQOuy7dKR3CabthJTTZP8AQg=
+github.com/markbates/refresh v1.4.5 h1:uhaMlPdvfW7MR+RLn1kgaWTMrn6v1DU/Kb36ydkkJCc=
+github.com/markbates/refresh v1.4.5/go.mod h1:uxgJcd3zFUMJjwu9bt30vmYbPz0PJjgfNP7MuG8Yrp4=
 github.com/markbates/sigtx v1.0.0 h1:y/xtkBvNPRjD4KeEplf4w9rJVSc23/xl+jXYGowTwy0=
 github.com/markbates/sigtx v1.0.0/go.mod h1:QF1Hv6Ic6Ca6W+T+DL0Y/ypborFKyvUY9HmuCD4VeTc=
 github.com/markbates/willie v1.0.6/go.mod h1:XtK+fmQ7tgVMIVAS1ghwuqVPup3GtgrNY3UCvUlPdzM=
@@ -160,7 +164,6 @@ github.com/markbates/willie v1.0.7 h1:0W+oMu9Ah+jvukKH9OmXFeKNDmbjqry8BcS9dQiRsh
 github.com/markbates/willie v1.0.7/go.mod h1:42G0jXiZEVLXutUa33JFH8tQW2dsHAqwYWNlVHfPtvM=
 github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@@ -170,7 +173,6 @@ github.com/microcosm-cc/bluemonday v1.0.0/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00v
 github.com/microcosm-cc/bluemonday v1.0.1 h1:SIYunPjnlXcW+gVfvm0IlSeR5U3WZUOLfVmqg85Go44=
 github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
 github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff h1:jM4Eo4qMmmcqePS3u6X2lcEELtVuXWkWJIS/pRI3oSk=
 github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -237,13 +239,11 @@ golang.org/x/crypto v0.0.0-20180808211826-de0752318171/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b h1:2b9XGzhjiYsYPnKXoEfL7klWZQIt8IfyRCz62gCqqlQ=
 golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180801234040-f4c29de78a2a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180808004115-f9ce57c11b24/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3 h1:czFLhve3vsQetD6JOJ8NZZvGQIXlnN3/yXxbT6/awxI=
 golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -255,7 +255,6 @@ golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180918153733-ee1b12c67af4 h1:h8ij2QOL81JqJ/Vi5Ru+hl4a1yct8+XDGrgBhG0XbuE=
 golang.org/x/sys v0.0.0-20180918153733-ee1b12c67af4/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -265,9 +264,8 @@ golang.org/x/tools v0.0.0-20180904205237-0aa4b8830f48/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24=
-google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
 gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=


Test patch:
diff --git a/default_context_test.go b/default_context_test.go
index 514d08d3..545a80ba 100644
--- a/default_context_test.go
+++ b/default_context_test.go
@@ -5,6 +5,7 @@ import (
 	"context"
 	"net/http"
 	"net/url"
+	"sync"
 	"testing"
 
 	"github.com/gobuffalo/buffalo/render"
@@ -19,6 +20,7 @@ func basicContext() DefaultContext {
 		logger:  NewLogger("debug"),
 		data:    make(map[string]interface{}),
 		flash:   &Flash{data: make(map[string][]string)},
+		moot:    &sync.RWMutex{},
 	}
 }