gopkg.in/yuukihogo/migrate.v3@v3.0.0/util.go (about) 1 package migrate 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 nurl "net/url" 8 "strings" 9 "time" 10 ) 11 12 // MultiError holds multiple errors. 13 type MultiError struct { 14 Errs []error 15 } 16 17 // NewMultiError returns an error type holding multiple errors. 18 func NewMultiError(errs ...error) MultiError { 19 compactErrs := make([]error, 0) 20 for _, e := range errs { 21 if e != nil { 22 compactErrs = append(compactErrs, e) 23 } 24 } 25 return MultiError{compactErrs} 26 } 27 28 // Error implements error. Mulitple errors are concatenated with 'and's. 29 func (m MultiError) Error() string { 30 var strs = make([]string, 0) 31 for _, e := range m.Errs { 32 if len(e.Error()) > 0 { 33 strs = append(strs, e.Error()) 34 } 35 } 36 return strings.Join(strs, " and ") 37 } 38 39 // suint safely converts int to uint 40 // see https://goo.gl/wEcqof 41 // see https://goo.gl/pai7Dr 42 func suint(n int) uint { 43 if n < 0 { 44 panic(fmt.Sprintf("suint(%v) expects input >= 0", n)) 45 } 46 return uint(n) 47 } 48 49 // newSlowReader turns an io.ReadCloser into a slow io.ReadCloser. 50 // Use this to simulate a slow internet connection. 51 func newSlowReader(r io.ReadCloser) io.ReadCloser { 52 return &slowReader{ 53 rx: r, 54 reader: bufio.NewReader(r), 55 } 56 } 57 58 type slowReader struct { 59 rx io.ReadCloser 60 reader *bufio.Reader 61 } 62 63 func (b *slowReader) Read(p []byte) (n int, err error) { 64 time.Sleep(10 * time.Millisecond) 65 c, err := b.reader.ReadByte() 66 if err != nil { 67 return 0, err 68 } else { 69 copy(p, []byte{c}) 70 return 1, nil 71 } 72 } 73 74 func (b *slowReader) Close() error { 75 return b.rx.Close() 76 } 77 78 var errNoScheme = fmt.Errorf("no scheme") 79 80 // schemeFromUrl returns the scheme from a URL string 81 func schemeFromUrl(url string) (string, error) { 82 u, err := nurl.Parse(url) 83 if err != nil { 84 return "", err 85 } 86 87 if len(u.Scheme) == 0 { 88 return "", errNoScheme 89 } 90 91 return u.Scheme, nil 92 } 93 94 // FilterCustomQuery filters all query values starting with `x-` 95 func FilterCustomQuery(u *nurl.URL) *nurl.URL { 96 ux := *u 97 vx := make(nurl.Values) 98 for k, v := range ux.Query() { 99 if len(k) <= 1 || (len(k) > 1 && k[0:2] != "x-") { 100 vx[k] = v 101 } 102 } 103 ux.RawQuery = vx.Encode() 104 return &ux 105 }