Browse Source

Update gorilla/mux, gorilla/context, and kr/pty deps

Docker-DCO-1.1-Signed-off-by: Andrew Page <admwiggin@gmail.com> (github: tianon)
Tianon Gravi 11 years ago
parent
commit
d98af1236c
30 changed files with 659 additions and 136 deletions
  1. 3 3
      hack/vendor.sh
  2. 7 0
      vendor/src/github.com/gorilla/context/.travis.yml
  3. 1 0
      vendor/src/github.com/gorilla/context/README.md
  4. 32 10
      vendor/src/github.com/gorilla/context/context.go
  5. 95 0
      vendor/src/github.com/gorilla/context/context_test.go
  6. 1 1
      vendor/src/github.com/gorilla/context/doc.go
  7. 7 0
      vendor/src/github.com/gorilla/mux/.travis.yml
  8. 1 0
      vendor/src/github.com/gorilla/mux/README.md
  9. 1 1
      vendor/src/github.com/gorilla/mux/doc.go
  10. 25 7
      vendor/src/github.com/gorilla/mux/mux.go
  11. 200 25
      vendor/src/github.com/gorilla/mux/mux_test.go
  12. 4 4
      vendor/src/github.com/gorilla/mux/old_test.go
  13. 10 7
      vendor/src/github.com/gorilla/mux/regexp.go
  14. 12 4
      vendor/src/github.com/gorilla/mux/route.go
  15. 11 0
      vendor/src/github.com/kr/pty/ioctl.go
  16. 39 0
      vendor/src/github.com/kr/pty/ioctl_bsd.go
  17. 42 0
      vendor/src/github.com/kr/pty/ioctl_linux.go
  18. 19 0
      vendor/src/github.com/kr/pty/mktypes.bash
  19. 8 17
      vendor/src/github.com/kr/pty/pty_darwin.go
  20. 40 20
      vendor/src/github.com/kr/pty/pty_freebsd.go
  21. 9 21
      vendor/src/github.com/kr/pty/pty_linux.go
  22. 0 16
      vendor/src/github.com/kr/pty/pty_unsupported.go
  23. 10 0
      vendor/src/github.com/kr/pty/types.go
  24. 15 0
      vendor/src/github.com/kr/pty/types_freebsd.go
  25. 9 0
      vendor/src/github.com/kr/pty/ztypes_386.go
  26. 9 0
      vendor/src/github.com/kr/pty/ztypes_amd64.go
  27. 9 0
      vendor/src/github.com/kr/pty/ztypes_arm.go
  28. 13 0
      vendor/src/github.com/kr/pty/ztypes_freebsd_386.go
  29. 14 0
      vendor/src/github.com/kr/pty/ztypes_freebsd_amd64.go
  30. 13 0
      vendor/src/github.com/kr/pty/ztypes_freebsd_arm.go

+ 3 - 3
hack/vendor.sh

@@ -39,11 +39,11 @@ clone() {
 	echo done
 	echo done
 }
 }
 
 
-clone git github.com/kr/pty 98c7b80083
+clone git github.com/kr/pty 67e2db24c8
 
 
-clone git github.com/gorilla/context 708054d61e5
+clone git github.com/gorilla/context b06ed15e1c
 
 
-clone git github.com/gorilla/mux 9b36453141c
+clone git github.com/gorilla/mux 136d54f81f
 
 
 clone git github.com/syndtr/gocapability 3c85049eae
 clone git github.com/syndtr/gocapability 3c85049eae
 
 

+ 7 - 0
vendor/src/github.com/gorilla/context/.travis.yml

@@ -0,0 +1,7 @@
+language: go
+
+go:
+  - 1.0
+  - 1.1
+  - 1.2
+  - tip

+ 1 - 0
vendor/src/github.com/gorilla/context/README.md

@@ -1,5 +1,6 @@
 context
 context
 =======
 =======
+[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context)
 
 
 gorilla/context is a general purpose registry for global request variables.
 gorilla/context is a general purpose registry for global request variables.
 
 

+ 32 - 10
vendor/src/github.com/gorilla/context/context.go

@@ -11,7 +11,7 @@ import (
 )
 )
 
 
 var (
 var (
-	mutex sync.Mutex
+	mutex sync.RWMutex
 	data  = make(map[*http.Request]map[interface{}]interface{})
 	data  = make(map[*http.Request]map[interface{}]interface{})
 	datat = make(map[*http.Request]int64)
 	datat = make(map[*http.Request]int64)
 )
 )
@@ -19,42 +19,64 @@ var (
 // Set stores a value for a given key in a given request.
 // Set stores a value for a given key in a given request.
 func Set(r *http.Request, key, val interface{}) {
 func Set(r *http.Request, key, val interface{}) {
 	mutex.Lock()
 	mutex.Lock()
-	defer mutex.Unlock()
 	if data[r] == nil {
 	if data[r] == nil {
 		data[r] = make(map[interface{}]interface{})
 		data[r] = make(map[interface{}]interface{})
 		datat[r] = time.Now().Unix()
 		datat[r] = time.Now().Unix()
 	}
 	}
 	data[r][key] = val
 	data[r][key] = val
+	mutex.Unlock()
 }
 }
 
 
 // Get returns a value stored for a given key in a given request.
 // Get returns a value stored for a given key in a given request.
 func Get(r *http.Request, key interface{}) interface{} {
 func Get(r *http.Request, key interface{}) interface{} {
-	mutex.Lock()
-	defer mutex.Unlock()
+	mutex.RLock()
 	if data[r] != nil {
 	if data[r] != nil {
+		mutex.RUnlock()
 		return data[r][key]
 		return data[r][key]
 	}
 	}
+	mutex.RUnlock()
 	return nil
 	return nil
 }
 }
 
 
 // GetOk returns stored value and presence state like multi-value return of map access.
 // GetOk returns stored value and presence state like multi-value return of map access.
 func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
 func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
-	mutex.Lock()
-	defer mutex.Unlock()
+	mutex.RLock()
 	if _, ok := data[r]; ok {
 	if _, ok := data[r]; ok {
 		value, ok := data[r][key]
 		value, ok := data[r][key]
+		mutex.RUnlock()
 		return value, ok
 		return value, ok
 	}
 	}
+	mutex.RUnlock()
 	return nil, false
 	return nil, false
 }
 }
 
 
+// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests.
+func GetAll(r *http.Request) map[interface{}]interface{} {
+	mutex.RLock()
+	if context, ok := data[r]; ok {
+		mutex.RUnlock()
+		return context
+	}
+	mutex.RUnlock()
+	return nil
+}
+
+// GetAllOk returns all stored values for the request as a map. It returns not
+// ok if the request was never registered.
+func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) {
+	mutex.RLock()
+	context, ok := data[r]
+	mutex.RUnlock()
+	return context, ok
+}
+
 // Delete removes a value stored for a given key in a given request.
 // Delete removes a value stored for a given key in a given request.
 func Delete(r *http.Request, key interface{}) {
 func Delete(r *http.Request, key interface{}) {
 	mutex.Lock()
 	mutex.Lock()
-	defer mutex.Unlock()
 	if data[r] != nil {
 	if data[r] != nil {
 		delete(data[r], key)
 		delete(data[r], key)
 	}
 	}
+	mutex.Unlock()
 }
 }
 
 
 // Clear removes all values stored for a given request.
 // Clear removes all values stored for a given request.
@@ -63,8 +85,8 @@ func Delete(r *http.Request, key interface{}) {
 // variables at the end of a request lifetime. See ClearHandler().
 // variables at the end of a request lifetime. See ClearHandler().
 func Clear(r *http.Request) {
 func Clear(r *http.Request) {
 	mutex.Lock()
 	mutex.Lock()
-	defer mutex.Unlock()
 	clear(r)
 	clear(r)
+	mutex.Unlock()
 }
 }
 
 
 // clear is Clear without the lock.
 // clear is Clear without the lock.
@@ -84,7 +106,6 @@ func clear(r *http.Request) {
 // periodically until the problem is fixed.
 // periodically until the problem is fixed.
 func Purge(maxAge int) int {
 func Purge(maxAge int) int {
 	mutex.Lock()
 	mutex.Lock()
-	defer mutex.Unlock()
 	count := 0
 	count := 0
 	if maxAge <= 0 {
 	if maxAge <= 0 {
 		count = len(data)
 		count = len(data)
@@ -92,13 +113,14 @@ func Purge(maxAge int) int {
 		datat = make(map[*http.Request]int64)
 		datat = make(map[*http.Request]int64)
 	} else {
 	} else {
 		min := time.Now().Unix() - int64(maxAge)
 		min := time.Now().Unix() - int64(maxAge)
-		for r, _ := range data {
+		for r := range data {
 			if datat[r] < min {
 			if datat[r] < min {
 				clear(r)
 				clear(r)
 				count++
 				count++
 			}
 			}
 		}
 		}
 	}
 	}
+	mutex.Unlock()
 	return count
 	return count
 }
 }
 
 

+ 95 - 0
vendor/src/github.com/gorilla/context/context_test.go

@@ -24,6 +24,7 @@ func TestContext(t *testing.T) {
 	}
 	}
 
 
 	r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
 	r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
+	emptyR, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
 
 
 	// Get()
 	// Get()
 	assertEqual(Get(r, key1), nil)
 	assertEqual(Get(r, key1), nil)
@@ -51,6 +52,26 @@ func TestContext(t *testing.T) {
 	assertEqual(value, nil)
 	assertEqual(value, nil)
 	assertEqual(ok, true)
 	assertEqual(ok, true)
 
 
+	// GetAll()
+	values := GetAll(r)
+	assertEqual(len(values), 3)
+
+	// GetAll() for empty request
+	values = GetAll(emptyR)
+	if values != nil {
+		t.Error("GetAll didn't return nil value for invalid request")
+	}
+
+	// GetAllOk()
+	values, ok = GetAllOk(r)
+	assertEqual(len(values), 3)
+	assertEqual(ok, true)
+
+	// GetAllOk() for empty request
+	values, ok = GetAllOk(emptyR)
+	assertEqual(value, nil)
+	assertEqual(ok, false)
+
 	// Delete()
 	// Delete()
 	Delete(r, key1)
 	Delete(r, key1)
 	assertEqual(Get(r, key1), nil)
 	assertEqual(Get(r, key1), nil)
@@ -64,3 +85,77 @@ func TestContext(t *testing.T) {
 	Clear(r)
 	Clear(r)
 	assertEqual(len(data), 0)
 	assertEqual(len(data), 0)
 }
 }
+
+func parallelReader(r *http.Request, key string, iterations int, wait, done chan struct{}) {
+	<-wait
+	for i := 0; i < iterations; i++ {
+		Get(r, key)
+	}
+	done <- struct{}{}
+
+}
+
+func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) {
+	<-wait
+	for i := 0; i < iterations; i++ {
+		Get(r, key)
+	}
+	done <- struct{}{}
+
+}
+
+func benchmarkMutex(b *testing.B, numReaders, numWriters, iterations int) {
+
+	b.StopTimer()
+	r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
+	done := make(chan struct{})
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		wait := make(chan struct{})
+
+		for i := 0; i < numReaders; i++ {
+			go parallelReader(r, "test", iterations, wait, done)
+		}
+
+		for i := 0; i < numWriters; i++ {
+			go parallelWriter(r, "test", "123", iterations, wait, done)
+		}
+
+		close(wait)
+
+		for i := 0; i < numReaders+numWriters; i++ {
+			<-done
+		}
+
+	}
+
+}
+
+func BenchmarkMutexSameReadWrite1(b *testing.B) {
+	benchmarkMutex(b, 1, 1, 32)
+}
+func BenchmarkMutexSameReadWrite2(b *testing.B) {
+	benchmarkMutex(b, 2, 2, 32)
+}
+func BenchmarkMutexSameReadWrite4(b *testing.B) {
+	benchmarkMutex(b, 4, 4, 32)
+}
+func BenchmarkMutex1(b *testing.B) {
+	benchmarkMutex(b, 2, 8, 32)
+}
+func BenchmarkMutex2(b *testing.B) {
+	benchmarkMutex(b, 16, 4, 64)
+}
+func BenchmarkMutex3(b *testing.B) {
+	benchmarkMutex(b, 1, 2, 128)
+}
+func BenchmarkMutex4(b *testing.B) {
+	benchmarkMutex(b, 128, 32, 256)
+}
+func BenchmarkMutex5(b *testing.B) {
+	benchmarkMutex(b, 1024, 2048, 64)
+}
+func BenchmarkMutex6(b *testing.B) {
+	benchmarkMutex(b, 2048, 1024, 512)
+}

+ 1 - 1
vendor/src/github.com/gorilla/context/doc.go

@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 // license that can be found in the LICENSE file.
 
 
 /*
 /*
-Package gorilla/context stores values shared during a request lifetime.
+Package context stores values shared during a request lifetime.
 
 
 For example, a router can set variables extracted from the URL and later
 For example, a router can set variables extracted from the URL and later
 application handlers can access those values, or it can be used to store
 application handlers can access those values, or it can be used to store

+ 7 - 0
vendor/src/github.com/gorilla/mux/.travis.yml

@@ -0,0 +1,7 @@
+language: go
+
+go:
+  - 1.0
+  - 1.1
+  - 1.2
+  - tip

+ 1 - 0
vendor/src/github.com/gorilla/mux/README.md

@@ -1,5 +1,6 @@
 mux
 mux
 ===
 ===
+[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux)
 
 
 gorilla/mux is a powerful URL router and dispatcher.
 gorilla/mux is a powerful URL router and dispatcher.
 
 

+ 1 - 1
vendor/src/github.com/gorilla/mux/doc.go

@@ -134,7 +134,7 @@ the inner routes use it as base for their paths:
 	// "/products/{key}/"
 	// "/products/{key}/"
 	s.HandleFunc("/{key}/", ProductHandler)
 	s.HandleFunc("/{key}/", ProductHandler)
 	// "/products/{key}/details"
 	// "/products/{key}/details"
-	s.HandleFunc("/{key}/details"), ProductDetailsHandler)
+	s.HandleFunc("/{key}/details", ProductDetailsHandler)
 
 
 Now let's see how to build registered URLs.
 Now let's see how to build registered URLs.
 
 

+ 25 - 7
vendor/src/github.com/gorilla/mux/mux.go

@@ -14,7 +14,7 @@ import (
 
 
 // NewRouter returns a new router instance.
 // NewRouter returns a new router instance.
 func NewRouter() *Router {
 func NewRouter() *Router {
-	return &Router{namedRoutes: make(map[string]*Route)}
+	return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
 }
 }
 
 
 // Router registers routes to be matched and dispatches a handler.
 // Router registers routes to be matched and dispatches a handler.
@@ -46,6 +46,8 @@ type Router struct {
 	namedRoutes map[string]*Route
 	namedRoutes map[string]*Route
 	// See Router.StrictSlash(). This defines the flag for new routes.
 	// See Router.StrictSlash(). This defines the flag for new routes.
 	strictSlash bool
 	strictSlash bool
+	// If true, do not clear the request context after handling the request
+	KeepContext bool
 }
 }
 
 
 // Match matches registered routes against the request.
 // Match matches registered routes against the request.
@@ -65,6 +67,14 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 	// Clean path to canonical form and redirect.
 	// Clean path to canonical form and redirect.
 	if p := cleanPath(req.URL.Path); p != req.URL.Path {
 	if p := cleanPath(req.URL.Path); p != req.URL.Path {
+
+		// Added 3 lines (Philip Schlump) - It was droping the query string and #whatever from query.
+		// This matches with fix in go 1.2 r.c. 4 for same problem.  Go Issue:
+		// http://code.google.com/p/go/issues/detail?id=5252
+		url := *req.URL
+		url.Path = p
+		p = url.String()
+
 		w.Header().Set("Location", p)
 		w.Header().Set("Location", p)
 		w.WriteHeader(http.StatusMovedPermanently)
 		w.WriteHeader(http.StatusMovedPermanently)
 		return
 		return
@@ -82,7 +92,9 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 		}
 		}
 		handler = r.NotFoundHandler
 		handler = r.NotFoundHandler
 	}
 	}
-	defer context.Clear(req)
+	if !r.KeepContext {
+		defer context.Clear(req)
+	}
 	handler.ServeHTTP(w, req)
 	handler.ServeHTTP(w, req)
 }
 }
 
 
@@ -97,14 +109,20 @@ func (r *Router) GetRoute(name string) *Route {
 	return r.getNamedRoutes()[name]
 	return r.getNamedRoutes()[name]
 }
 }
 
 
-// StrictSlash defines the slash behavior for new routes.
+// StrictSlash defines the trailing slash behavior for new routes. The initial
+// value is false.
 //
 //
 // When true, if the route path is "/path/", accessing "/path" will redirect
 // When true, if the route path is "/path/", accessing "/path" will redirect
-// to the former and vice versa.
+// to the former and vice versa. In other words, your application will always
+// see the path as specified in the route.
+//
+// When false, if the route path is "/path", accessing "/path/" will not match
+// this route and vice versa.
 //
 //
-// Special case: when a route sets a path prefix, strict slash is
-// automatically set to false for that route because the redirect behavior
-// can't be determined for prefixes.
+// Special case: when a route sets a path prefix using the PathPrefix() method,
+// strict slash is ignored for that route because the redirect behavior can't
+// be determined from a prefix alone. However, any subrouters created from that
+// route inherit the original StrictSlash setting.
 func (r *Router) StrictSlash(value bool) *Router {
 func (r *Router) StrictSlash(value bool) *Router {
 	r.strictSlash = value
 	r.strictSlash = value
 	return r
 	return r

+ 200 - 25
vendor/src/github.com/gorilla/mux/mux_test.go

@@ -8,16 +8,19 @@ import (
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"testing"
 	"testing"
+
+	"github.com/gorilla/context"
 )
 )
 
 
 type routeTest struct {
 type routeTest struct {
-	title       string            // title of the test
-	route       *Route            // the route being tested
-	request     *http.Request     // a request to test the route
-	vars        map[string]string // the expected vars of the match
-	host        string            // the expected host of the match
-	path        string            // the expected path of the match
-	shouldMatch bool              // whether the request is expected to match the route at all
+	title          string            // title of the test
+	route          *Route            // the route being tested
+	request        *http.Request     // a request to test the route
+	vars           map[string]string // the expected vars of the match
+	host           string            // the expected host of the match
+	path           string            // the expected path of the match
+	shouldMatch    bool              // whether the request is expected to match the route at all
+	shouldRedirect bool              // whether the request should result in a redirect
 }
 }
 
 
 func TestHost(t *testing.T) {
 func TestHost(t *testing.T) {
@@ -149,6 +152,33 @@ func TestPath(t *testing.T) {
 			path:        "/111/222/333",
 			path:        "/111/222/333",
 			shouldMatch: true,
 			shouldMatch: true,
 		},
 		},
+		{
+			title:       "Path route, match with trailing slash in request and path",
+			route:       new(Route).Path("/111/"),
+			request:     newRequest("GET", "http://localhost/111/"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111/",
+			shouldMatch: true,
+		},
+		{
+			title:       "Path route, do not match with trailing slash in path",
+			route:       new(Route).Path("/111/"),
+			request:     newRequest("GET", "http://localhost/111"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111",
+			shouldMatch: false,
+		},
+		{
+			title:       "Path route, do not match with trailing slash in request",
+			route:       new(Route).Path("/111"),
+			request:     newRequest("GET", "http://localhost/111/"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111/",
+			shouldMatch: false,
+		},
 		{
 		{
 			title:       "Path route, wrong path in request in request URL",
 			title:       "Path route, wrong path in request in request URL",
 			route:       new(Route).Path("/111/222/333"),
 			route:       new(Route).Path("/111/222/333"),
@@ -212,6 +242,15 @@ func TestPathPrefix(t *testing.T) {
 			path:        "/111",
 			path:        "/111",
 			shouldMatch: true,
 			shouldMatch: true,
 		},
 		},
+		{
+			title:       "PathPrefix route, match substring",
+			route:       new(Route).PathPrefix("/1"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/1",
+			shouldMatch: true,
+		},
 		{
 		{
 			title:       "PathPrefix route, URL prefix in request does not match",
 			title:       "PathPrefix route, URL prefix in request does not match",
 			route:       new(Route).PathPrefix("/111"),
 			route:       new(Route).PathPrefix("/111"),
@@ -414,6 +453,15 @@ func TestQueries(t *testing.T) {
 			path:        "",
 			path:        "",
 			shouldMatch: true,
 			shouldMatch: true,
 		},
 		},
+		{
+			title:       "Queries route, match with a query string",
+			route:       new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
+			request:     newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
 		{
 		{
 			title:       "Queries route, bad query",
 			title:       "Queries route, bad query",
 			route:       new(Route).Queries("foo", "bar", "baz", "ding"),
 			route:       new(Route).Queries("foo", "bar", "baz", "ding"),
@@ -568,26 +616,74 @@ func TestNamedRoutes(t *testing.T) {
 }
 }
 
 
 func TestStrictSlash(t *testing.T) {
 func TestStrictSlash(t *testing.T) {
-	var r *Router
-	var req *http.Request
-	var route *Route
-	var match *RouteMatch
-	var matched bool
-
-	// StrictSlash should be ignored for path prefix.
-	// So we register a route ending in slash but it doesn't attempt to add
-	// the slash for a path not ending in slash.
-	r = NewRouter()
+	r := NewRouter()
 	r.StrictSlash(true)
 	r.StrictSlash(true)
-	route = r.NewRoute().PathPrefix("/static/")
-	req, _ = http.NewRequest("GET", "http://localhost/static/logo.png", nil)
-	match = new(RouteMatch)
-	matched = r.Match(req, match)
-	if !matched {
-		t.Errorf("Should match request %q -- %v", req.URL.Path, getRouteTemplate(route))
+
+	tests := []routeTest{
+		{
+			title:          "Redirect path without slash",
+			route:          r.NewRoute().Path("/111/"),
+			request:        newRequest("GET", "http://localhost/111"),
+			vars:           map[string]string{},
+			host:           "",
+			path:           "/111/",
+			shouldMatch:    true,
+			shouldRedirect: true,
+		},
+		{
+			title:          "Do not redirect path with slash",
+			route:          r.NewRoute().Path("/111/"),
+			request:        newRequest("GET", "http://localhost/111/"),
+			vars:           map[string]string{},
+			host:           "",
+			path:           "/111/",
+			shouldMatch:    true,
+			shouldRedirect: false,
+		},
+		{
+			title:          "Redirect path with slash",
+			route:          r.NewRoute().Path("/111"),
+			request:        newRequest("GET", "http://localhost/111/"),
+			vars:           map[string]string{},
+			host:           "",
+			path:           "/111",
+			shouldMatch:    true,
+			shouldRedirect: true,
+		},
+		{
+			title:          "Do not redirect path without slash",
+			route:          r.NewRoute().Path("/111"),
+			request:        newRequest("GET", "http://localhost/111"),
+			vars:           map[string]string{},
+			host:           "",
+			path:           "/111",
+			shouldMatch:    true,
+			shouldRedirect: false,
+		},
+		{
+			title:          "Propagate StrictSlash to subrouters",
+			route:          r.NewRoute().PathPrefix("/static/").Subrouter().Path("/images/"),
+			request:        newRequest("GET", "http://localhost/static/images"),
+			vars:           map[string]string{},
+			host:           "",
+			path:           "/static/images/",
+			shouldMatch:    true,
+			shouldRedirect: true,
+		},
+		{
+			title:          "Ignore StrictSlash for path prefix",
+			route:          r.NewRoute().PathPrefix("/static/"),
+			request:        newRequest("GET", "http://localhost/static/logo.png"),
+			vars:           map[string]string{},
+			host:           "",
+			path:           "/static/",
+			shouldMatch:    true,
+			shouldRedirect: false,
+		},
 	}
 	}
-	if match.Handler != nil {
-		t.Errorf("Should not redirect")
+
+	for _, test := range tests {
+		testRoute(t, test)
 	}
 	}
 }
 }
 
 
@@ -616,6 +712,7 @@ func testRoute(t *testing.T, test routeTest) {
 	host := test.host
 	host := test.host
 	path := test.path
 	path := test.path
 	url := test.host + test.path
 	url := test.host + test.path
+	shouldRedirect := test.shouldRedirect
 
 
 	var match RouteMatch
 	var match RouteMatch
 	ok := route.Match(request, &match)
 	ok := route.Match(request, &match)
@@ -653,6 +750,84 @@ func testRoute(t *testing.T, test routeTest) {
 				return
 				return
 			}
 			}
 		}
 		}
+		if shouldRedirect && match.Handler == nil {
+			t.Errorf("(%v) Did not redirect", test.title)
+			return
+		}
+		if !shouldRedirect && match.Handler != nil {
+			t.Errorf("(%v) Unexpected redirect", test.title)
+			return
+		}
+	}
+}
+
+// Tests that the context is cleared or not cleared properly depending on
+// the configuration of the router
+func TestKeepContext(t *testing.T) {
+	func1 := func(w http.ResponseWriter, r *http.Request) {}
+
+	r := NewRouter()
+	r.HandleFunc("/", func1).Name("func1")
+
+	req, _ := http.NewRequest("GET", "http://localhost/", nil)
+	context.Set(req, "t", 1)
+
+	res := new(http.ResponseWriter)
+	r.ServeHTTP(*res, req)
+
+	if _, ok := context.GetOk(req, "t"); ok {
+		t.Error("Context should have been cleared at end of request")
+	}
+
+	r.KeepContext = true
+
+	req, _ = http.NewRequest("GET", "http://localhost/", nil)
+	context.Set(req, "t", 1)
+
+	r.ServeHTTP(*res, req)
+	if _, ok := context.GetOk(req, "t"); !ok {
+		t.Error("Context should NOT have been cleared at end of request")
+	}
+
+}
+
+type TestA301ResponseWriter struct {
+	hh     http.Header
+	status int
+}
+
+func (ho TestA301ResponseWriter) Header() http.Header {
+	return http.Header(ho.hh)
+}
+
+func (ho TestA301ResponseWriter) Write(b []byte) (int, error) {
+	return 0, nil
+}
+
+func (ho TestA301ResponseWriter) WriteHeader(code int) {
+	ho.status = code
+}
+
+func Test301Redirect(t *testing.T) {
+	m := make(http.Header)
+
+	func1 := func(w http.ResponseWriter, r *http.Request) {}
+	func2 := func(w http.ResponseWriter, r *http.Request) {}
+
+	r := NewRouter()
+	r.HandleFunc("/api/", func2).Name("func2")
+	r.HandleFunc("/", func1).Name("func1")
+
+	req, _ := http.NewRequest("GET", "http://localhost//api/?abc=def", nil)
+
+	res := TestA301ResponseWriter{
+		hh:     m,
+		status: 0,
+	}
+	r.ServeHTTP(&res, req)
+
+	if "http://localhost/api/?abc=def" != res.hh["Location"][0] {
+		t.Errorf("Should have complete URL with query string")
 	}
 	}
 }
 }
 
 

+ 4 - 4
vendor/src/github.com/gorilla/mux/old_test.go

@@ -96,8 +96,8 @@ func TestRouteMatchers(t *testing.T) {
 		method = "GET"
 		method = "GET"
 		headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
 		headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
 		resultVars = map[bool]map[string]string{
 		resultVars = map[bool]map[string]string{
-			true:  map[string]string{"var1": "www", "var2": "product", "var3": "42"},
-			false: map[string]string{},
+			true:  {"var1": "www", "var2": "product", "var3": "42"},
+			false: {},
 		}
 		}
 	}
 	}
 
 
@@ -110,8 +110,8 @@ func TestRouteMatchers(t *testing.T) {
 		method = "POST"
 		method = "POST"
 		headers = map[string]string{"Content-Type": "application/json"}
 		headers = map[string]string{"Content-Type": "application/json"}
 		resultVars = map[bool]map[string]string{
 		resultVars = map[bool]map[string]string{
-			true:  map[string]string{"var4": "google", "var5": "product", "var6": "42"},
-			false: map[string]string{},
+			true:  {"var4": "google", "var5": "product", "var6": "42"},
+			false: {},
 		}
 		}
 	}
 	}
 
 

+ 10 - 7
vendor/src/github.com/gorilla/mux/regexp.go

@@ -98,12 +98,13 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, strictSlash bool) (*rout
 	}
 	}
 	// Done!
 	// Done!
 	return &routeRegexp{
 	return &routeRegexp{
-		template:  template,
-		matchHost: matchHost,
-		regexp:    reg,
-		reverse:   reverse.String(),
-		varsN:     varsN,
-		varsR:     varsR,
+		template:    template,
+		matchHost:   matchHost,
+		strictSlash: strictSlash,
+		regexp:      reg,
+		reverse:     reverse.String(),
+		varsN:       varsN,
+		varsR:       varsR,
 	}, nil
 	}, nil
 }
 }
 
 
@@ -114,6 +115,8 @@ type routeRegexp struct {
 	template string
 	template string
 	// True for host match, false for path match.
 	// True for host match, false for path match.
 	matchHost bool
 	matchHost bool
+	// The strictSlash value defined on the route, but disabled if PathPrefix was used.
+	strictSlash bool
 	// Expanded regexp.
 	// Expanded regexp.
 	regexp *regexp.Regexp
 	regexp *regexp.Regexp
 	// Reverse template.
 	// Reverse template.
@@ -216,7 +219,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
 				m.Vars[v] = pathVars[k+1]
 				m.Vars[v] = pathVars[k+1]
 			}
 			}
 			// Check if we should redirect.
 			// Check if we should redirect.
-			if r.strictSlash {
+			if v.path.strictSlash {
 				p1 := strings.HasSuffix(req.URL.Path, "/")
 				p1 := strings.HasSuffix(req.URL.Path, "/")
 				p2 := strings.HasSuffix(v.path.template, "/")
 				p2 := strings.HasSuffix(v.path.template, "/")
 				if p1 != p2 {
 				if p1 != p2 {

+ 12 - 4
vendor/src/github.com/gorilla/mux/route.go

@@ -259,7 +259,8 @@ func (r *Route) Methods(methods ...string) *Route {
 // Path -----------------------------------------------------------------------
 // Path -----------------------------------------------------------------------
 
 
 // Path adds a matcher for the URL path.
 // Path adds a matcher for the URL path.
-// It accepts a template with zero or more URL variables enclosed by {}.
+// It accepts a template with zero or more URL variables enclosed by {}. The
+// template must start with a "/".
 // Variables can define an optional regexp pattern to me matched:
 // Variables can define an optional regexp pattern to me matched:
 //
 //
 // - {name} matches anything until the next slash.
 // - {name} matches anything until the next slash.
@@ -283,9 +284,16 @@ func (r *Route) Path(tpl string) *Route {
 
 
 // PathPrefix -----------------------------------------------------------------
 // PathPrefix -----------------------------------------------------------------
 
 
-// PathPrefix adds a matcher for the URL path prefix.
+// PathPrefix adds a matcher for the URL path prefix. This matches if the given
+// template is a prefix of the full URL path. See Route.Path() for details on
+// the tpl argument.
+//
+// Note that it does not treat slashes specially ("/foobar/" will be matched by
+// the prefix "/foo") so you may want to use a trailing slash here.
+//
+// Also note that the setting of Router.StrictSlash() has no effect on routes
+// with a PathPrefix matcher.
 func (r *Route) PathPrefix(tpl string) *Route {
 func (r *Route) PathPrefix(tpl string) *Route {
-	r.strictSlash = false
 	r.err = r.addRegexpMatcher(tpl, false, true)
 	r.err = r.addRegexpMatcher(tpl, false, true)
 	return r
 	return r
 }
 }
@@ -328,7 +336,7 @@ func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool {
 }
 }
 
 
 // Schemes adds a matcher for URL schemes.
 // Schemes adds a matcher for URL schemes.
-// It accepts a sequence schemes to be matched, e.g.: "http", "https".
+// It accepts a sequence of schemes to be matched, e.g.: "http", "https".
 func (r *Route) Schemes(schemes ...string) *Route {
 func (r *Route) Schemes(schemes ...string) *Route {
 	for k, v := range schemes {
 	for k, v := range schemes {
 		schemes[k] = strings.ToLower(v)
 		schemes[k] = strings.ToLower(v)

+ 11 - 0
vendor/src/github.com/kr/pty/ioctl.go

@@ -0,0 +1,11 @@
+package pty
+
+import "syscall"
+
+func ioctl(fd, cmd, ptr uintptr) error {
+	_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
+	if e != 0 {
+		return e
+	}
+	return nil
+}

+ 39 - 0
vendor/src/github.com/kr/pty/ioctl_bsd.go

@@ -0,0 +1,39 @@
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package pty
+
+// from <sys/ioccom.h>
+const (
+	_IOC_VOID    uintptr = 0x20000000
+	_IOC_OUT     uintptr = 0x40000000
+	_IOC_IN      uintptr = 0x80000000
+	_IOC_IN_OUT  uintptr = _IOC_OUT | _IOC_IN
+	_IOC_DIRMASK         = _IOC_VOID | _IOC_OUT | _IOC_IN
+
+	_IOC_PARAM_SHIFT = 13
+	_IOC_PARAM_MASK  = (1 << _IOC_PARAM_SHIFT) - 1
+)
+
+func _IOC_PARM_LEN(ioctl uintptr) uintptr {
+	return (ioctl >> 16) & _IOC_PARAM_MASK
+}
+
+func _IOC(inout uintptr, group byte, ioctl_num uintptr, param_len uintptr) uintptr {
+	return inout | (param_len&_IOC_PARAM_MASK)<<16 | uintptr(group)<<8 | ioctl_num
+}
+
+func _IO(group byte, ioctl_num uintptr) uintptr {
+	return _IOC(_IOC_VOID, group, ioctl_num, 0)
+}
+
+func _IOR(group byte, ioctl_num uintptr, param_len uintptr) uintptr {
+	return _IOC(_IOC_OUT, group, ioctl_num, param_len)
+}
+
+func _IOW(group byte, ioctl_num uintptr, param_len uintptr) uintptr {
+	return _IOC(_IOC_IN, group, ioctl_num, param_len)
+}
+
+func _IOWR(group byte, ioctl_num uintptr, param_len uintptr) uintptr {
+	return _IOC(_IOC_IN_OUT, group, ioctl_num, param_len)
+}

+ 42 - 0
vendor/src/github.com/kr/pty/ioctl_linux.go

@@ -0,0 +1,42 @@
+package pty
+
+// from <asm-generic/ioctl.h>
+const (
+	_IOC_NRBITS   = 8
+	_IOC_TYPEBITS = 8
+
+	_IOC_SIZEBITS = 14
+	_IOC_DIRBITS  = 2
+
+	_IOC_NRSHIFT   = 0
+	_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
+	_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
+	_IOC_DIRSHIFT  = _IOC_SIZESHIFT + _IOC_SIZEBITS
+
+	_IOC_NONE  uint = 0
+	_IOC_WRITE uint = 1
+	_IOC_READ  uint = 2
+)
+
+func _IOC(dir uint, ioctl_type byte, nr byte, size uintptr) uintptr {
+	return (uintptr(dir)<<_IOC_DIRSHIFT |
+		uintptr(ioctl_type)<<_IOC_TYPESHIFT |
+		uintptr(nr)<<_IOC_NRSHIFT |
+		size<<_IOC_SIZESHIFT)
+}
+
+func _IO(ioctl_type byte, nr byte) uintptr {
+	return _IOC(_IOC_NONE, ioctl_type, nr, 0)
+}
+
+func _IOR(ioctl_type byte, nr byte, size uintptr) uintptr {
+	return _IOC(_IOC_READ, ioctl_type, nr, size)
+}
+
+func _IOW(ioctl_type byte, nr byte, size uintptr) uintptr {
+	return _IOC(_IOC_WRITE, ioctl_type, nr, size)
+}
+
+func _IOWR(ioctl_type byte, nr byte, size uintptr) uintptr {
+	return _IOC(_IOC_READ|_IOC_WRITE, ioctl_type, nr, size)
+}

+ 19 - 0
vendor/src/github.com/kr/pty/mktypes.bash

@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+GOOSARCH="${GOOS}_${GOARCH}"
+case "$GOOSARCH" in
+_* | *_ | _)
+	echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
+	exit 1
+	;;
+esac
+
+GODEFS="go tool cgo -godefs"
+
+$GODEFS types.go |gofmt > ztypes_$GOARCH.go
+
+case $GOOS in
+freebsd)
+	$GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go
+	;;
+esac

+ 8 - 17
vendor/src/github.com/kr/pty/pty_darwin.go

@@ -7,9 +7,6 @@ import (
 	"unsafe"
 	"unsafe"
 )
 )
 
 
-// see ioccom.h
-const sys_IOCPARM_MASK = 0x1fff
-
 func open() (pty, tty *os.File, err error) {
 func open() (pty, tty *os.File, err error) {
 	p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
 	p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
 	if err != nil {
 	if err != nil {
@@ -39,9 +36,13 @@ func open() (pty, tty *os.File, err error) {
 }
 }
 
 
 func ptsname(f *os.File) (string, error) {
 func ptsname(f *os.File) (string, error) {
-	var n [(syscall.TIOCPTYGNAME >> 16) & sys_IOCPARM_MASK]byte
+	n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME))
+
+	err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0])))
+	if err != nil {
+		return "", err
+	}
 
 
-	ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n)))
 	for i, c := range n {
 	for i, c := range n {
 		if c == 0 {
 		if c == 0 {
 			return string(n[:i]), nil
 			return string(n[:i]), nil
@@ -51,19 +52,9 @@ func ptsname(f *os.File) (string, error) {
 }
 }
 
 
 func grantpt(f *os.File) error {
 func grantpt(f *os.File) error {
-	var u int
-	return ioctl(f.Fd(), syscall.TIOCPTYGRANT, uintptr(unsafe.Pointer(&u)))
+	return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0)
 }
 }
 
 
 func unlockpt(f *os.File) error {
 func unlockpt(f *os.File) error {
-	var u int
-	return ioctl(f.Fd(), syscall.TIOCPTYUNLK, uintptr(unsafe.Pointer(&u)))
-}
-
-func ioctl(fd, cmd, ptr uintptr) error {
-	_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
-	if e != 0 {
-		return syscall.ENOTTY
-	}
-	return nil
+	return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0)
 }
 }

+ 40 - 20
vendor/src/github.com/kr/pty/pty_freebsd.go

@@ -1,53 +1,73 @@
 package pty
 package pty
 
 
 import (
 import (
+	"errors"
 	"os"
 	"os"
-	"strconv"
 	"syscall"
 	"syscall"
 	"unsafe"
 	"unsafe"
 )
 )
 
 
-const (
-	sys_TIOCGPTN   = 0x4004740F
-	sys_TIOCSPTLCK = 0x40045431
-)
+func posix_openpt(oflag int) (fd int, err error) {
+	r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
 
 
 func open() (pty, tty *os.File, err error) {
 func open() (pty, tty *os.File, err error) {
-	p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
+	fd, err := posix_openpt(syscall.O_RDWR | syscall.O_CLOEXEC)
 	if err != nil {
 	if err != nil {
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 
 
+	p := os.NewFile(uintptr(fd), "/dev/pts")
 	sname, err := ptsname(p)
 	sname, err := ptsname(p)
 	if err != nil {
 	if err != nil {
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 
 
-	t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
+	t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0)
 	if err != nil {
 	if err != nil {
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 	return p, t, nil
 	return p, t, nil
 }
 }
 
 
+func isptmaster(fd uintptr) (bool, error) {
+	err := ioctl(fd, syscall.TIOCPTMASTER, 0)
+	return err == nil, err
+}
+
+var (
+	emptyFiodgnameArg fiodgnameArg
+	ioctl_FIODGNAME   = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg))
+)
+
 func ptsname(f *os.File) (string, error) {
 func ptsname(f *os.File) (string, error) {
-	var n int
-	err := ioctl(f.Fd(), sys_TIOCGPTN, &n)
+	master, err := isptmaster(f.Fd())
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
-	return "/dev/pts/" + strconv.Itoa(n), nil
-}
+	if !master {
+		return "", syscall.EINVAL
+	}
 
 
-func ioctl(fd uintptr, cmd uintptr, data *int) error {
-	_, _, e := syscall.Syscall(
-		syscall.SYS_IOCTL,
-		fd,
-		cmd,
-		uintptr(unsafe.Pointer(data)),
+	const n = _C_SPECNAMELEN + 1
+	var (
+		buf = make([]byte, n)
+		arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))}
 	)
 	)
-	if e != 0 {
-		return syscall.ENOTTY
+	err = ioctl(f.Fd(), ioctl_FIODGNAME, uintptr(unsafe.Pointer(&arg)))
+	if err != nil {
+		return "", err
+	}
+
+	for i, c := range buf {
+		if c == 0 {
+			return string(buf[:i]), nil
+		}
 	}
 	}
-	return nil
+	return "", errors.New("FIODGNAME string not NUL-terminated")
 }
 }

+ 9 - 21
vendor/src/github.com/kr/pty/pty_linux.go

@@ -7,9 +7,9 @@ import (
 	"unsafe"
 	"unsafe"
 )
 )
 
 
-const (
-	sys_TIOCGPTN   = 0x80045430
-	sys_TIOCSPTLCK = 0x40045431
+var (
+	ioctl_TIOCGPTN   = _IOR('T', 0x30, unsafe.Sizeof(_C_uint(0))) /* Get Pty Number (of pty-mux device) */
+	ioctl_TIOCSPTLCK = _IOW('T', 0x31, unsafe.Sizeof(_C_int(0)))  /* Lock/unlock Pty */
 )
 )
 
 
 func open() (pty, tty *os.File, err error) {
 func open() (pty, tty *os.File, err error) {
@@ -36,28 +36,16 @@ func open() (pty, tty *os.File, err error) {
 }
 }
 
 
 func ptsname(f *os.File) (string, error) {
 func ptsname(f *os.File) (string, error) {
-	var n int
-	err := ioctl(f.Fd(), sys_TIOCGPTN, &n)
+	var n _C_uint
+	err := ioctl(f.Fd(), ioctl_TIOCGPTN, uintptr(unsafe.Pointer(&n)))
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
-	return "/dev/pts/" + strconv.Itoa(n), nil
+	return "/dev/pts/" + strconv.Itoa(int(n)), nil
 }
 }
 
 
 func unlockpt(f *os.File) error {
 func unlockpt(f *os.File) error {
-	var u int
-	return ioctl(f.Fd(), sys_TIOCSPTLCK, &u)
-}
-
-func ioctl(fd uintptr, cmd uintptr, data *int) error {
-	_, _, e := syscall.Syscall(
-		syscall.SYS_IOCTL,
-		fd,
-		cmd,
-		uintptr(unsafe.Pointer(data)),
-	)
-	if e != 0 {
-		return syscall.ENOTTY
-	}
-	return nil
+	var u _C_int
+	// use TIOCSPTLCK with a zero valued arg to clear the slave pty lock
+	return ioctl(f.Fd(), ioctl_TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
 }
 }

+ 0 - 16
vendor/src/github.com/kr/pty/pty_unsupported.go

@@ -9,19 +9,3 @@ import (
 func open() (pty, tty *os.File, err error) {
 func open() (pty, tty *os.File, err error) {
 	return nil, nil, ErrUnsupported
 	return nil, nil, ErrUnsupported
 }
 }
-
-func ptsname(f *os.File) (string, error) {
-	return "", ErrUnsupported
-}
-
-func grantpt(f *os.File) error {
-	return ErrUnsupported
-}
-
-func unlockpt(f *os.File) error {
-	return ErrUnsupported
-}
-
-func ioctl(fd, cmd, ptr uintptr) error {
-	return ErrUnsupported
-}

+ 10 - 0
vendor/src/github.com/kr/pty/types.go

@@ -0,0 +1,10 @@
+// +build ignore
+
+package pty
+
+import "C"
+
+type (
+	_C_int  C.int
+	_C_uint C.uint
+)

+ 15 - 0
vendor/src/github.com/kr/pty/types_freebsd.go

@@ -0,0 +1,15 @@
+// +build ignore
+
+package pty
+
+/*
+#include <sys/param.h>
+#include <sys/filio.h>
+*/
+import "C"
+
+const (
+	_C_SPECNAMELEN = C.SPECNAMELEN /* max length of devicename */
+)
+
+type fiodgnameArg C.struct_fiodgname_arg

+ 9 - 0
vendor/src/github.com/kr/pty/ztypes_386.go

@@ -0,0 +1,9 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types.go
+
+package pty
+
+type (
+	_C_int  int32
+	_C_uint uint32
+)

+ 9 - 0
vendor/src/github.com/kr/pty/ztypes_amd64.go

@@ -0,0 +1,9 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types.go
+
+package pty
+
+type (
+	_C_int  int32
+	_C_uint uint32
+)

+ 9 - 0
vendor/src/github.com/kr/pty/ztypes_arm.go

@@ -0,0 +1,9 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types.go
+
+package pty
+
+type (
+	_C_int  int32
+	_C_uint uint32
+)

+ 13 - 0
vendor/src/github.com/kr/pty/ztypes_freebsd_386.go

@@ -0,0 +1,13 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_freebsd.go
+
+package pty
+
+const (
+	_C_SPECNAMELEN = 0x3f
+)
+
+type fiodgnameArg struct {
+	Len int32
+	Buf *byte
+}

+ 14 - 0
vendor/src/github.com/kr/pty/ztypes_freebsd_amd64.go

@@ -0,0 +1,14 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_freebsd.go
+
+package pty
+
+const (
+	_C_SPECNAMELEN = 0x3f
+)
+
+type fiodgnameArg struct {
+	Len       int32
+	Pad_cgo_0 [4]byte
+	Buf       *byte
+}

+ 13 - 0
vendor/src/github.com/kr/pty/ztypes_freebsd_arm.go

@@ -0,0 +1,13 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_freebsd.go
+
+package pty
+
+const (
+	_C_SPECNAMELEN = 0x3f
+)
+
+type fiodgnameArg struct {
+	Len int32
+	Buf *byte
+}