diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 6fae154..923453d 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,33 +1,35 @@ { "ImportPath": "github.com/concourse/github-release-resource", "GoVersion": "go1.5.1", + "Packages": [ + "./..." + ], "Deps": [ { "ImportPath": "code.google.com/p/goauth2/oauth", - "Comment": "weekly-56", - "Rev": "afe77d958c701557ec5dc56f6936fcc194d15520" + "Comment": "weekly-57", + "Rev": "'222e66a2882ef45c3153c86c0aa82fe65fc29a78'" }, { - "ImportPath": "github.com/blang/semver", - "Comment": "v3.0.0", - "Rev": "2f3112b6f8f18f9df8743cc75ed51da08094ef6a" + "ImportPath": "github.com/cppforlife/go-semi-semantic/version", + "Rev": "a7ba07c61e58e6df7693d49a13d24f533182518a" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "9ebc6c4ed925b1323a0b11cea09e527cdc4e557c" + "Rev": "d3d78384b82d449651d2435ed329d70f7c48aa56" }, { "ImportPath": "github.com/google/go-querystring/query", - "Rev": "d8840cbb2baa915f4836edda4750050a2c0b7aea" + "Rev": "2a60fc2ba6c19de80291203597d752e9ba58e4c0" }, { "ImportPath": "github.com/mitchellh/colorstring", - "Rev": "15fc698eaae194ff160846daf77922a45b9290a7" + "Rev": "8631ce90f28644f54aeedcb3e389a85174e067d1" }, { "ImportPath": "github.com/onsi/ginkgo", - "Comment": "v1.1.0-38-g5ed93e4", - "Rev": "5ed93e443a4b7dfe9f5e95ca87e6082e503021d2" + "Comment": "v1.2.0-22-g39d2c24", + "Rev": "39d2c24f8a92c88f7e7f4d8ec6c80d3cc8f5ac65" }, { "ImportPath": "github.com/onsi/gomega", diff --git a/Godeps/_workspace/src/code.google.com/p/goauth2/LICENSE b/Godeps/_workspace/src/code.google.com/p/goauth2/LICENSE new file mode 100644 index 0000000..6765f09 --- /dev/null +++ b/Godeps/_workspace/src/code.google.com/p/goauth2/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The goauth2 Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT +OWNER 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/Godeps/_workspace/src/code.google.com/p/goauth2/PATENTS b/Godeps/_workspace/src/code.google.com/p/goauth2/PATENTS new file mode 100644 index 0000000..9e87163 --- /dev/null +++ b/Godeps/_workspace/src/code.google.com/p/goauth2/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the goauth2 project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/Godeps/_workspace/src/code.google.com/p/goauth2/oauth/oauth.go b/Godeps/_workspace/src/code.google.com/p/goauth2/oauth/oauth.go index 6f1b6c1..fc968ae 100644 --- a/Godeps/_workspace/src/code.google.com/p/goauth2/oauth/oauth.go +++ b/Godeps/_workspace/src/code.google.com/p/goauth2/oauth/oauth.go @@ -4,6 +4,10 @@ // Package oauth supports making OAuth2-authenticated HTTP requests. // +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// !!! DEPRECATED. Use golang.org/x/oauth2 instead. !!! +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// // Example usage: // // // Specify your configuration. (typically as a global variable) diff --git a/Godeps/_workspace/src/github.com/blang/semver/LICENSE b/Godeps/_workspace/src/github.com/blang/semver/LICENSE deleted file mode 100644 index 5ba5c86..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License - -Copyright (c) 2014 Benedikt Lang - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/Godeps/_workspace/src/github.com/blang/semver/README.md b/Godeps/_workspace/src/github.com/blang/semver/README.md deleted file mode 100644 index 5171c5c..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/README.md +++ /dev/null @@ -1,142 +0,0 @@ -semver for golang [![Build Status](https://drone.io/github.com/blang/semver/status.png)](https://drone.io/github.com/blang/semver/latest) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master) -====== - -semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`. - -Usage ------ -```bash -$ go get github.com/blang/semver -``` -Note: Always vendor your dependencies or fix on a specific version tag. - -```go -import github.com/blang/semver -v1, err := semver.Make("1.0.0-beta") -v2, err := semver.Make("2.0.0-beta") -v1.Compare(v2) -``` - -Also check the [GoDocs](http://godoc.org/github.com/blang/semver). - -Why should I use this lib? ------ - -- Fully spec compatible -- No reflection -- No regex -- Fully tested (Coverage >99%) -- Readable parsing/validation errors -- Fast (See [Benchmarks](#benchmarks)) -- Only Stdlib -- Uses values instead of pointers -- Many features, see below - - -Features ------ - -- Parsing and validation at all levels -- Comparator-like comparisons -- Compare Helper Methods -- InPlace manipulation -- Sortable (implements sort.Interface) -- database/sql compatible (sql.Scanner/Valuer) -- encoding/json compatible (json.Marshaler/Unmarshaler) - - -Example ------ - -Have a look at full examples in [examples/main.go](examples/main.go) - -```go -import github.com/blang/semver - -v, err := semver.Make("0.0.1-alpha.preview+123.github") -fmt.Printf("Major: %d\n", v.Major) -fmt.Printf("Minor: %d\n", v.Minor) -fmt.Printf("Patch: %d\n", v.Patch) -fmt.Printf("Pre: %s\n", v.Pre) -fmt.Printf("Build: %s\n", v.Build) - -// Prerelease versions array -if len(v.Pre) > 0 { - fmt.Println("Prerelease versions:") - for i, pre := range v.Pre { - fmt.Printf("%d: %q\n", i, pre) - } -} - -// Build meta data array -if len(v.Build) > 0 { - fmt.Println("Build meta data:") - for i, build := range v.Build { - fmt.Printf("%d: %q\n", i, build) - } -} - -v001, err := semver.Make("0.0.1") -// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE -v001.GT(v) == true -v.LT(v001) == true -v.GTE(v) == true -v.LTE(v) == true - -// Or use v.Compare(v2) for comparisons (-1, 0, 1): -v001.Compare(v) == 1 -v.Compare(v001) == -1 -v.Compare(v) == 0 - -// Manipulate Version in place: -v.Pre[0], err = semver.NewPRVersion("beta") -if err != nil { - fmt.Printf("Error parsing pre release version: %q", err) -} - -fmt.Println("\nValidate versions:") -v.Build[0] = "?" - -err = v.Validate() -if err != nil { - fmt.Printf("Validation failed: %s\n", err) -} -``` - -Benchmarks ------ - - BenchmarkParseSimple 5000000 328 ns/op 49 B/op 1 allocs/op - BenchmarkParseComplex 1000000 2105 ns/op 263 B/op 7 allocs/op - BenchmarkParseAverage 1000000 1301 ns/op 168 B/op 4 allocs/op - BenchmarkStringSimple 10000000 130 ns/op 5 B/op 1 allocs/op - BenchmarkStringLarger 5000000 280 ns/op 32 B/op 2 allocs/op - BenchmarkStringComplex 3000000 512 ns/op 80 B/op 3 allocs/op - BenchmarkStringAverage 5000000 387 ns/op 47 B/op 2 allocs/op - BenchmarkValidateSimple 500000000 7.92 ns/op 0 B/op 0 allocs/op - BenchmarkValidateComplex 2000000 923 ns/op 0 B/op 0 allocs/op - BenchmarkValidateAverage 5000000 452 ns/op 0 B/op 0 allocs/op - BenchmarkCompareSimple 100000000 11.2 ns/op 0 B/op 0 allocs/op - BenchmarkCompareComplex 50000000 40.9 ns/op 0 B/op 0 allocs/op - BenchmarkCompareAverage 50000000 43.8 ns/op 0 B/op 0 allocs/op - BenchmarkSort 5000000 436 ns/op 259 B/op 2 allocs/op - -See benchmark cases at [semver_test.go](semver_test.go) - - -Motivation ------ - -I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like. - - -Contribution ------ - -Feel free to make a pull request. For bigger changes create a issue first to discuss about it. - - -License ------ - -See [LICENSE](LICENSE) file. diff --git a/Godeps/_workspace/src/github.com/blang/semver/examples/main.go b/Godeps/_workspace/src/github.com/blang/semver/examples/main.go deleted file mode 100644 index f36c983..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/examples/main.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "fmt" - "github.com/blang/semver" -) - -func main() { - v, err := semver.Parse("0.0.1-alpha.preview.222+123.github") - if err != nil { - fmt.Printf("Error while parsing (not valid): %q", err) - } - fmt.Printf("Version to string: %q\n", v) - - fmt.Printf("Major: %d\n", v.Major) - fmt.Printf("Minor: %d\n", v.Minor) - fmt.Printf("Patch: %d\n", v.Patch) - - // Prerelease versions - if len(v.Pre) > 0 { - fmt.Println("Prerelease versions:") - for i, pre := range v.Pre { - fmt.Printf("%d: %q\n", i, pre) - } - } - - // Build meta data - if len(v.Build) > 0 { - fmt.Println("Build meta data:") - for i, build := range v.Build { - fmt.Printf("%d: %q\n", i, build) - } - } - - // Make == Parse (Value), New for Pointer - v001, err := semver.Make("0.0.1") - - fmt.Println("\nUse Version.Compare for comparisons (-1, 0, 1):") - fmt.Printf("%q is greater than %q: Compare == %d\n", v001, v, v001.Compare(v)) - fmt.Printf("%q is less than %q: Compare == %d\n", v, v001, v.Compare(v001)) - fmt.Printf("%q is equal to %q: Compare == %d\n", v, v, v.Compare(v)) - - fmt.Println("\nUse comparison helpers returning booleans:") - fmt.Printf("%q is greater than %q: %t\n", v001, v, v001.GT(v)) - fmt.Printf("%q is greater than equal %q: %t\n", v001, v, v001.GTE(v)) - fmt.Printf("%q is greater than equal %q: %t\n", v, v, v.GTE(v)) - fmt.Printf("%q is less than %q: %t\n", v, v001, v.LT(v001)) - fmt.Printf("%q is less than equal %q: %t\n", v, v001, v.LTE(v001)) - fmt.Printf("%q is less than equal %q: %t\n", v, v, v.LTE(v)) - - fmt.Println("\nManipulate Version in place:") - v.Pre[0], err = semver.NewPRVersion("beta") - if err != nil { - fmt.Printf("Error parsing pre release version: %q", err) - } - fmt.Printf("Version to string: %q\n", v) - - fmt.Println("\nCompare Prerelease versions:") - pre1, _ := semver.NewPRVersion("123") - pre2, _ := semver.NewPRVersion("alpha") - pre3, _ := semver.NewPRVersion("124") - fmt.Printf("%q is less than %q: Compare == %d\n", pre1, pre2, pre1.Compare(pre2)) - fmt.Printf("%q is greater than %q: Compare == %d\n", pre3, pre1, pre3.Compare(pre1)) - fmt.Printf("%q is equal to %q: Compare == %d\n", pre1, pre1, pre1.Compare(pre1)) - - fmt.Println("\nValidate versions:") - v.Build[0] = "?" - - err = v.Validate() - if err != nil { - fmt.Printf("Validation failed: %s\n", err) - } - - fmt.Println("Create valid build meta data:") - b1, _ := semver.NewBuildVersion("build123") - v.Build[0] = b1 - fmt.Printf("Version with new build version %q\n", v) - - _, err = semver.NewBuildVersion("build?123") - if err != nil { - fmt.Printf("Create build version failed: %s\n", err) - } -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/json.go b/Godeps/_workspace/src/github.com/blang/semver/json.go deleted file mode 100644 index a74bf7c..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/json.go +++ /dev/null @@ -1,23 +0,0 @@ -package semver - -import ( - "encoding/json" -) - -// MarshalJSON implements the encoding/json.Marshaler interface. -func (v Version) MarshalJSON() ([]byte, error) { - return json.Marshal(v.String()) -} - -// UnmarshalJSON implements the encoding/json.Unmarshaler interface. -func (v *Version) UnmarshalJSON(data []byte) (err error) { - var versionString string - - if err = json.Unmarshal(data, &versionString); err != nil { - return - } - - *v, err = Parse(versionString) - - return -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/semver.go b/Godeps/_workspace/src/github.com/blang/semver/semver.go deleted file mode 100644 index c82fe66..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/semver.go +++ /dev/null @@ -1,398 +0,0 @@ -package semver - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -const ( - numbers string = "0123456789" - alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" - alphanum = alphas + numbers -) - -// Latest fully supported spec version -var SPEC_VERSION = Version{ - Major: 2, - Minor: 0, - Patch: 0, -} - -type Version struct { - Major uint64 - Minor uint64 - Patch uint64 - Pre []PRVersion - Build []string //No Precendence -} - -// Version to string -func (v Version) String() string { - b := make([]byte, 0, 5) - b = strconv.AppendUint(b, v.Major, 10) - b = append(b, '.') - b = strconv.AppendUint(b, v.Minor, 10) - b = append(b, '.') - b = strconv.AppendUint(b, v.Patch, 10) - - if len(v.Pre) > 0 { - b = append(b, '-') - b = append(b, v.Pre[0].String()...) - - for _, pre := range v.Pre[1:] { - b = append(b, '.') - b = append(b, pre.String()...) - } - } - - if len(v.Build) > 0 { - b = append(b, '+') - b = append(b, v.Build[0]...) - - for _, build := range v.Build[1:] { - b = append(b, '.') - b = append(b, build...) - } - } - - return string(b) -} - -// Checks if v is equal to o. -func (v Version) Equals(o Version) bool { - return (v.Compare(o) == 0) -} - -// Checks if v is equal to o. -func (v Version) EQ(o Version) bool { - return (v.Compare(o) == 0) -} - -// Checks if v is not equal to o. -func (v Version) NE(o Version) bool { - return (v.Compare(o) != 0) -} - -// Checks if v is greater than o. -func (v Version) GT(o Version) bool { - return (v.Compare(o) == 1) -} - -// Checks if v is greater than or equal to o. -func (v Version) GTE(o Version) bool { - return (v.Compare(o) >= 0) -} - -// Checks if v is greater than or equal to o. -func (v Version) GE(o Version) bool { - return (v.Compare(o) >= 0) -} - -// Checks if v is less than o. -func (v Version) LT(o Version) bool { - return (v.Compare(o) == -1) -} - -// Checks if v is less than or equal to o. -func (v Version) LTE(o Version) bool { - return (v.Compare(o) <= 0) -} - -// Checks if v is less than or equal to o. -func (v Version) LE(o Version) bool { - return (v.Compare(o) <= 0) -} - -// Compares Versions v to o: -// -1 == v is less than o -// 0 == v is equal to o -// 1 == v is greater than o -func (v Version) Compare(o Version) int { - if v.Major != o.Major { - if v.Major > o.Major { - return 1 - } else { - return -1 - } - } - if v.Minor != o.Minor { - if v.Minor > o.Minor { - return 1 - } else { - return -1 - } - } - if v.Patch != o.Patch { - if v.Patch > o.Patch { - return 1 - } else { - return -1 - } - } - - // Quick comparison if a version has no prerelease versions - if len(v.Pre) == 0 && len(o.Pre) == 0 { - return 0 - } else if len(v.Pre) == 0 && len(o.Pre) > 0 { - return 1 - } else if len(v.Pre) > 0 && len(o.Pre) == 0 { - return -1 - } else { - - i := 0 - for ; i < len(v.Pre) && i < len(o.Pre); i++ { - if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 { - continue - } else if comp == 1 { - return 1 - } else { - return -1 - } - } - - // If all pr versions are the equal but one has further prversion, this one greater - if i == len(v.Pre) && i == len(o.Pre) { - return 0 - } else if i == len(v.Pre) && i < len(o.Pre) { - return -1 - } else { - return 1 - } - - } -} - -// Validates v and returns error in case -func (v Version) Validate() error { - // Major, Minor, Patch already validated using uint64 - - for _, pre := range v.Pre { - if !pre.IsNum { //Numeric prerelease versions already uint64 - if len(pre.VersionStr) == 0 { - return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr) - } - if !containsOnly(pre.VersionStr, alphanum) { - return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr) - } - } - } - - for _, build := range v.Build { - if len(build) == 0 { - return fmt.Errorf("Build meta data can not be empty %q", build) - } - if !containsOnly(build, alphanum) { - return fmt.Errorf("Invalid character(s) found in build meta data %q", build) - } - } - - return nil -} - -// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error -func New(s string) (vp *Version, err error) { - v, err := Parse(s) - vp = &v - return -} - -// Make is an alias for Parse, parses version string and returns a validated Version or error -func Make(s string) (Version, error) { - return Parse(s) -} - -// Parse parses version string and returns a validated Version or error -func Parse(s string) (Version, error) { - if len(s) == 0 { - return Version{}, errors.New("Version string empty") - } - - // Split into major.minor.(patch+pr+meta) - parts := strings.SplitN(s, ".", 3) - if len(parts) != 3 { - return Version{}, errors.New("No Major.Minor.Patch elements found") - } - - // Major - if !containsOnly(parts[0], numbers) { - return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0]) - } - if hasLeadingZeroes(parts[0]) { - return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0]) - } - major, err := strconv.ParseUint(parts[0], 10, 64) - if err != nil { - return Version{}, err - } - - // Minor - if !containsOnly(parts[1], numbers) { - return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1]) - } - if hasLeadingZeroes(parts[1]) { - return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1]) - } - minor, err := strconv.ParseUint(parts[1], 10, 64) - if err != nil { - return Version{}, err - } - - v := Version{} - v.Major = major - v.Minor = minor - - var build, prerelease []string - patchStr := parts[2] - - if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 { - build = strings.Split(patchStr[buildIndex+1:], ".") - patchStr = patchStr[:buildIndex] - } - - if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 { - prerelease = strings.Split(patchStr[preIndex+1:], ".") - patchStr = patchStr[:preIndex] - } - - if !containsOnly(patchStr, numbers) { - return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr) - } - if hasLeadingZeroes(patchStr) { - return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr) - } - patch, err := strconv.ParseUint(patchStr, 10, 64) - if err != nil { - return Version{}, err - } - - v.Patch = patch - - // Prerelease - for _, prstr := range prerelease { - parsedPR, err := NewPRVersion(prstr) - if err != nil { - return Version{}, err - } - v.Pre = append(v.Pre, parsedPR) - } - - // Build meta data - for _, str := range build { - if len(str) == 0 { - return Version{}, errors.New("Build meta data is empty") - } - if !containsOnly(str, alphanum) { - return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str) - } - v.Build = append(v.Build, str) - } - - return v, nil -} - -// MustParse is like Parse but panics if the version cannot be parsed. -func MustParse(s string) Version { - v, err := Parse(s) - if err != nil { - panic(`semver: Parse(` + s + `): ` + err.Error()) - } - return v -} - -// PreRelease Version -type PRVersion struct { - VersionStr string - VersionNum uint64 - IsNum bool -} - -// Creates a new valid prerelease version -func NewPRVersion(s string) (PRVersion, error) { - if len(s) == 0 { - return PRVersion{}, errors.New("Prerelease is empty") - } - v := PRVersion{} - if containsOnly(s, numbers) { - if hasLeadingZeroes(s) { - return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s) - } - num, err := strconv.ParseUint(s, 10, 64) - - // Might never be hit, but just in case - if err != nil { - return PRVersion{}, err - } - v.VersionNum = num - v.IsNum = true - } else if containsOnly(s, alphanum) { - v.VersionStr = s - v.IsNum = false - } else { - return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s) - } - return v, nil -} - -// Is pre release version numeric? -func (v PRVersion) IsNumeric() bool { - return v.IsNum -} - -// Compares PreRelease Versions v to o: -// -1 == v is less than o -// 0 == v is equal to o -// 1 == v is greater than o -func (v PRVersion) Compare(o PRVersion) int { - if v.IsNum && !o.IsNum { - return -1 - } else if !v.IsNum && o.IsNum { - return 1 - } else if v.IsNum && o.IsNum { - if v.VersionNum == o.VersionNum { - return 0 - } else if v.VersionNum > o.VersionNum { - return 1 - } else { - return -1 - } - } else { // both are Alphas - if v.VersionStr == o.VersionStr { - return 0 - } else if v.VersionStr > o.VersionStr { - return 1 - } else { - return -1 - } - } -} - -// PreRelease version to string -func (v PRVersion) String() string { - if v.IsNum { - return strconv.FormatUint(v.VersionNum, 10) - } - return v.VersionStr -} - -func containsOnly(s string, set string) bool { - return strings.IndexFunc(s, func(r rune) bool { - return !strings.ContainsRune(set, r) - }) == -1 -} - -func hasLeadingZeroes(s string) bool { - return len(s) > 1 && s[0] == '0' -} - -// Creates a new valid build version -func NewBuildVersion(s string) (string, error) { - if len(s) == 0 { - return "", errors.New("Buildversion is empty") - } - if !containsOnly(s, alphanum) { - return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s) - } - return s, nil -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/sort.go b/Godeps/_workspace/src/github.com/blang/semver/sort.go deleted file mode 100644 index b250f58..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/sort.go +++ /dev/null @@ -1,24 +0,0 @@ -package semver - -import ( - "sort" -) - -type Versions []Version - -func (s Versions) Len() int { - return len(s) -} - -func (s Versions) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s Versions) Less(i, j int) bool { - return s[i].LT(s[j]) -} - -// Sort sorts a slice of versions -func Sort(versions []Version) { - sort.Sort(Versions(versions)) -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/sql.go b/Godeps/_workspace/src/github.com/blang/semver/sql.go deleted file mode 100644 index b8d4b6a..0000000 --- a/Godeps/_workspace/src/github.com/blang/semver/sql.go +++ /dev/null @@ -1,30 +0,0 @@ -package semver - -import ( - "database/sql/driver" - "fmt" -) - -// Scan implements the database/sql.Scanner interface. -func (v *Version) Scan(src interface{}) (err error) { - var str string - switch src := src.(type) { - case string: - str = src - case []byte: - str = string(src) - default: - return fmt.Errorf("Version.Scan: cannot convert %T to string.", src) - } - - if t, err := Parse(str); err == nil { - *v = t - } - - return -} - -// Value implements the database/sql/driver.Valuer interface. -func (s Version) Value() (driver.Value, error) { - return s.String(), nil -} diff --git a/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/LICENSE b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/LICENSE new file mode 100644 index 0000000..cad237a --- /dev/null +++ b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2014 Dmitriy Kalinin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/ver_seg_comp_int.go b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/ver_seg_comp_int.go new file mode 100644 index 0000000..1492adc --- /dev/null +++ b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/ver_seg_comp_int.go @@ -0,0 +1,49 @@ +package version + +import ( + "errors" + "regexp" + "strconv" +) + +var ( + verSegCompIntRegexp = regexp.MustCompile(`\A[0-9]+\z`) +) + +type VerSegCompInt struct{ I int } + +func NewVerSegCompIntFromString(piece string) (VerSegCompInt, bool, error) { + if !verSegCompIntRegexp.MatchString(piece) { + return VerSegCompInt{}, false, nil + } + + i, err := strconv.Atoi(piece) + if err != nil { + return VerSegCompInt{}, true, err + } + + return VerSegCompInt{i}, true, nil +} + +func (i VerSegCompInt) Validate() error { + if i.I < 0 { + return errors.New("Expected integer component to be greater than or equal to 0") + } + + return nil +} + +func (i VerSegCompInt) Compare(other VerSegComp) int { + otherTyped := other.(VerSegCompInt) + switch { + case i.I < otherTyped.I: + return -1 + case i.I == otherTyped.I: + return 0 + case i.I > otherTyped.I: + return 1 + } + panic("unreachable") +} + +func (i VerSegCompInt) AsString() string { return strconv.Itoa(i.I) } diff --git a/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/ver_seg_comp_str.go b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/ver_seg_comp_str.go new file mode 100644 index 0000000..eafbc52 --- /dev/null +++ b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/ver_seg_comp_str.go @@ -0,0 +1,43 @@ +package version + +import ( + "errors" + "regexp" +) + +var ( + verSegCompStrRegexp = regexp.MustCompile(`\A[0-9A-Za-z_\-]+\z`) +) + +type VerSegCompStr struct{ S string } + +func NewVerSegCompStrFromString(piece string) (VerSegCompStr, bool) { + if !verSegCompStrRegexp.MatchString(piece) { + return VerSegCompStr{}, false + } + + return VerSegCompStr{piece}, true +} + +func (s VerSegCompStr) Validate() error { + if len(s.S) == 0 { + return errors.New("Expected string component to be non-empty") + } + + return nil +} + +func (s VerSegCompStr) Compare(other VerSegComp) int { + otherTyped := other.(VerSegCompStr) + switch { + case s.S < otherTyped.S: + return -1 + case s.S == otherTyped.S: + return 0 + case s.S > otherTyped.S: + return 1 + } + panic("unreachable") +} + +func (s VerSegCompStr) AsString() string { return s.S } diff --git a/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/version.go b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/version.go new file mode 100644 index 0000000..d44ea66 --- /dev/null +++ b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/version.go @@ -0,0 +1,152 @@ +package version + +import ( + "errors" + "fmt" + "regexp" +) + +var ( + versionRegexp = matchingRegexp{regexp.MustCompile(`\A(?P[0-9A-Za-z_\.]+)(\-(?P[0-9A-Za-z_\-\.]+))?(\+(?P[0-9A-Za-z_\-\.]+))?\z`)} +) + +type matchingRegexp struct { + *regexp.Regexp +} + +type Version struct { + Release, PreRelease, PostRelease VersionSegment + + Segments []VersionSegment +} + +func NewVersionFromString(v string) (Version, error) { + var err error + + if len(v) == 0 { + return Version{}, errors.New("Expected version to be non-empty string") + } + + captures := versionRegexp.FindStringSubmatchMap(v) + if len(captures) == 0 { + errMsg := fmt.Sprintf("Expected version '%s' to match version format", v) + return Version{}, errors.New(errMsg) + } + + release := VersionSegment{} + preRelease := VersionSegment{} + postRelease := VersionSegment{} + + if releaseStr, ok := captures["release"]; ok { + release, err = NewVersionSegmentFromString(releaseStr) + if err != nil { + return Version{}, err + } + } + + if preReleaseStr, ok := captures["pre_release"]; ok { + preRelease, err = NewVersionSegmentFromString(preReleaseStr) + if err != nil { + return Version{}, err + } + } + + if postReleaseStr, ok := captures["post_release"]; ok { + postRelease, err = NewVersionSegmentFromString(postReleaseStr) + if err != nil { + return Version{}, err + } + } + + return NewVersion(release, preRelease, postRelease) +} + +func NewVersion(release, preRelease, postRelease VersionSegment) (Version, error) { + if release.Empty() { + return Version{}, errors.New("Expected to non-empty release segment for constructing version") + } + + version := Version{ + Release: release, + PreRelease: preRelease, + PostRelease: postRelease, + Segments: []VersionSegment{release, preRelease, postRelease}, + } + + return version, nil +} + +func (v Version) String() string { return v.AsString() } + +func (v Version) AsString() string { + result := v.Release.AsString() + + if !v.PreRelease.Empty() { + result += "-" + v.PreRelease.AsString() + } + + if !v.PostRelease.Empty() { + result += "+" + v.PostRelease.AsString() + } + + return result +} + +func (v Version) Compare(other Version) int { + result := v.Release.Compare(other.Release) + if result != 0 { + return result + } + + if !v.PreRelease.Empty() || !other.PreRelease.Empty() { + if v.PreRelease.Empty() { + return 1 + } + if other.PreRelease.Empty() { + return -1 + } + result = v.PreRelease.Compare(other.PreRelease) + if result != 0 { + return result + } + } + + if !v.PostRelease.Empty() || !other.PostRelease.Empty() { + if v.PostRelease.Empty() { + return -1 + } + if other.PostRelease.Empty() { + return 1 + } + result = v.PostRelease.Compare(other.PostRelease) + if result != 0 { + return result + } + } + + return 0 +} + +func (v Version) IsEq(other Version) bool { return v.Compare(other) == 0 } +func (v Version) IsGt(other Version) bool { return v.Compare(other) == 1 } +func (v Version) IsLt(other Version) bool { return v.Compare(other) == -1 } + +func (r *matchingRegexp) FindStringSubmatchMap(s string) map[string]string { + captures := map[string]string{} + + match := r.FindStringSubmatch(s) + if match == nil { + return captures + } + + for i, name := range r.SubexpNames() { + // 0 is a whole regex + if i == 0 || name == "" || match[i] == "" { + continue + } + + captures[name] = match[i] + } + + return captures +} diff --git a/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/version_segment.go b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/version_segment.go new file mode 100644 index 0000000..dd75627 --- /dev/null +++ b/Godeps/_workspace/src/github.com/cppforlife/go-semi-semantic/version/version_segment.go @@ -0,0 +1,143 @@ +package version + +import ( + "errors" + "fmt" + "strings" +) + +type VerSegComp interface { + Validate() error + // Compare should panic if incompatible interface is given + Compare(VerSegComp) int + AsString() string +} + +type VersionSegment struct { + Components []VerSegComp +} + +func NewVersionSegmentFromString(v string) (VersionSegment, error) { + pieces := strings.Split(v, ".") + + components := []VerSegComp{} + + for _, p := range pieces { + i, matchedI, err := NewVerSegCompIntFromString(p) + if err != nil { + errMsg := fmt.Sprintf("Expected component '%s' from version segment '%s' to be a parseable integer: %s", p, v, err) + return VersionSegment{}, errors.New(errMsg) + } + + if matchedI { + components = append(components, i) + } else if s, matched := NewVerSegCompStrFromString(p); matched { + components = append(components, s) + } else { + errMsg := fmt.Sprintf("Expected component '%s' from version segment '%s' to be either an integer or a formatted string", p, v) + return VersionSegment{}, errors.New(errMsg) + } + } + + return VersionSegment{components}, nil +} + +func NewVersionSegment(components []VerSegComp) (VersionSegment, error) { + if len(components) == 0 { + return VersionSegment{}, errors.New("Expected version segment to be build from at least one component") + } + + for _, c := range components { + err := c.Validate() + if err != nil { + return VersionSegment{}, err + } + } + + return VersionSegment{components}, nil +} + +func (s VersionSegment) Empty() bool { return len(s.Components) == 0 } + +func (s VersionSegment) AsString() string { + result := "" + + for i, c := range s.Components { + result += c.AsString() + + if i < len(s.Components)-1 { + result += "." + } + } + + return result +} + +func (s VersionSegment) Compare(other VersionSegment) int { + a := s.Components + b := other.Components + + if len(a) > len(b) { + comparison := s.compareArrays(a[0:len(b)], b) + if comparison != 0 { + return comparison + } + if !s.isAllZeros(a[len(b):len(a)]) { + return 1 + } + return 0 + } + + if len(a) < len(b) { + comparison := s.compareArrays(a, b[0:len(a)]) + if comparison != 0 { + return comparison + } + if !s.isAllZeros(b[len(a):len(b)]) { + return -1 + } + return 0 + } + + return s.compareArrays(a, b) +} + +func (s VersionSegment) IsEq(other VersionSegment) bool { return s.Compare(other) == 0 } +func (s VersionSegment) IsGt(other VersionSegment) bool { return s.Compare(other) == 1 } +func (s VersionSegment) IsLt(other VersionSegment) bool { return s.Compare(other) == -1 } + +// compareArrays compares 2 equally sized a & b +func (s VersionSegment) compareArrays(a, b []VerSegComp) int { + for i, v1 := range a { + v2 := b[i] + + _, v1IsStr := v1.(VerSegCompStr) + _, v1IsInt := v1.(VerSegCompInt) + _, v2IsStr := v2.(VerSegCompStr) + _, v2IsInt := v2.(VerSegCompInt) + + if v1IsStr && v2IsInt { + return 1 + } else if v1IsInt && v2IsStr { + return -1 + } + + comparison := v1.Compare(v2) + if comparison != 0 { + return comparison + } + } + + return 0 +} + +func (s VersionSegment) isAllZeros(a []VerSegComp) bool { + for _, v := range a { + vTyped, ok := v.(VerSegCompInt) + if !ok || vTyped.I != 0 { + return false + } + } + + return true +} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/LICENSE b/Godeps/_workspace/src/github.com/golang/protobuf/LICENSE new file mode 100644 index 0000000..1b1b192 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/protobuf/LICENSE @@ -0,0 +1,31 @@ +Go support for Protocol Buffers - Google's data interchange format + +Copyright 2010 The Go Authors. All rights reserved. +https://github.com/golang/protobuf + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT +OWNER 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/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go index 89d0caa..7321e1a 100644 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go +++ b/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go @@ -1115,9 +1115,8 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { return nil } - keys := v.MapKeys() - sort.Sort(mapKeys(keys)) - for _, key := range keys { + // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. + for _, key := range v.MapKeys() { val := v.MapIndex(key) // The only illegal map entry values are nil message pointers. diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go index abbf758..dcabe3b 100644 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go +++ b/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go @@ -216,7 +216,7 @@ The resulting file, test.pb.go, is: To create and play with a Test object: -package main + package main import ( "log" diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go index ec31258..b4aaac5 100644 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go +++ b/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go @@ -37,6 +37,7 @@ package proto import ( "fmt" + "log" "os" "reflect" "sort" @@ -809,3 +810,29 @@ func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[ func EnumValueMap(enumType string) map[string]int32 { return enumValueMaps[enumType] } + +// A registry of all linked message types. +// The string is a fully-qualified proto name ("pkg.Message"). +var ( + protoTypes = make(map[string]reflect.Type) + revProtoTypes = make(map[reflect.Type]string) +) + +// RegisterType is called from generated code and maps from the fully qualified +// proto name to the type (pointer to struct) of the protocol buffer. +func RegisterType(x Message, name string) { + if _, ok := protoTypes[name]; ok { + // TODO: Some day, make this a panic. + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoTypes[name] = t + revProtoTypes[t] = name +} + +// MessageName returns the fully-qualified proto name for the given message type. +func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] } + +// MessageType returns the message type (pointer to struct) for a named message. +func MessageType(name string) reflect.Type { return protoTypes[name] } diff --git a/Godeps/_workspace/src/github.com/google/go-querystring/LICENSE b/Godeps/_workspace/src/github.com/google/go-querystring/LICENSE new file mode 100644 index 0000000..ae121a1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/google/go-querystring/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Google. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT +OWNER 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/Godeps/_workspace/src/github.com/google/go-querystring/query/encode.go b/Godeps/_workspace/src/github.com/google/go-querystring/query/encode.go index 31d36e7..90dcabb 100644 --- a/Godeps/_workspace/src/github.com/google/go-querystring/query/encode.go +++ b/Godeps/_workspace/src/github.com/google/go-querystring/query/encode.go @@ -22,7 +22,6 @@ package query import ( "bytes" - "errors" "fmt" "net/url" "reflect" @@ -88,7 +87,9 @@ type Encoder interface { // Slice and Array values default to encoding as multiple URL values of the // same name. Including the "comma" option signals that the field should be // encoded as a single comma-delimited value. Including the "space" option -// similarly encodes the value as a single space-delimited string. +// similarly encodes the value as a single space-delimited string. Including +// the "brackets" option signals that the multiple URL values should have "[]" +// appended to the value name. // // Anonymous struct fields are usually encoded as if their inner exported // fields were fields in the outer struct, subject to the standard Go @@ -97,32 +98,41 @@ type Encoder interface { // // Non-nil pointer values are encoded as the value pointed to. // +// Nested structs are encoded including parent fields in value names for +// scoping. e.g: +// +// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" +// // All other values are encoded using their default string representation. // // Multiple fields that encode to the same URL parameter name will be included // as multiple URL values of the same name. func Values(v interface{}) (url.Values, error) { + values := make(url.Values) val := reflect.ValueOf(v) for val.Kind() == reflect.Ptr { if val.IsNil() { - return nil, errors.New("query: Values() expects non-nil value") + return values, nil } val = val.Elem() } + if v == nil { + return values, nil + } + if val.Kind() != reflect.Struct { return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) } - values := make(url.Values) - err := reflectValue(values, val) + err := reflectValue(values, val, "") return values, err } // reflectValue populates the values parameter from the struct fields in val. // Embedded structs are followed recursively (using the rules defined in the // Values function documentation) breadth-first. -func reflectValue(values url.Values, val reflect.Value) error { +func reflectValue(values url.Values, val reflect.Value, scope string) error { var embedded []reflect.Value typ := val.Type() @@ -148,11 +158,19 @@ func reflectValue(values url.Values, val reflect.Value) error { name = sf.Name } + if scope != "" { + name = scope + "[" + name + "]" + } + if opts.Contains("omitempty") && isEmptyValue(sv) { continue } if sv.Type().Implements(encoderType) { + if !reflect.Indirect(sv).IsValid() { + sv = reflect.New(sv.Type().Elem()) + } + m := sv.Interface().(Encoder) if err := m.EncodeValues(name, &values); err != nil { return err @@ -166,6 +184,8 @@ func reflectValue(values url.Values, val reflect.Value) error { del = ',' } else if opts.Contains("space") { del = ' ' + } else if opts.Contains("brackets") { + name = name + "[]" } if del != 0 { @@ -188,11 +208,28 @@ func reflectValue(values url.Values, val reflect.Value) error { continue } + if sv.Type() == timeType { + values.Add(name, valueString(sv, opts)) + continue + } + + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + + if sv.Kind() == reflect.Struct { + reflectValue(values, sv, name) + continue + } + values.Add(name, valueString(sv, opts)) } for _, f := range embedded { - if err := reflectValue(values, f); err != nil { + if err := reflectValue(values, f, scope); err != nil { return err } } diff --git a/Godeps/_workspace/src/github.com/mitchellh/colorstring/README.md b/Godeps/_workspace/src/github.com/mitchellh/colorstring/README.md index 66134ff..0654d45 100644 --- a/Godeps/_workspace/src/github.com/mitchellh/colorstring/README.md +++ b/Godeps/_workspace/src/github.com/mitchellh/colorstring/README.md @@ -23,7 +23,7 @@ For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/col Usage is easy enough: ```go -fmt.Println(colorstring.Color("[blue]Hello [red]World!")) +colorstring.Println("[blue]Hello [red]World!") ``` Additionally, the `Colorize` struct can be used to set options such as diff --git a/Godeps/_workspace/src/github.com/mitchellh/colorstring/colorstring.go b/Godeps/_workspace/src/github.com/mitchellh/colorstring/colorstring.go index 0ed7651..3de5b24 100644 --- a/Godeps/_workspace/src/github.com/mitchellh/colorstring/colorstring.go +++ b/Godeps/_workspace/src/github.com/mitchellh/colorstring/colorstring.go @@ -5,7 +5,9 @@ package colorstring import ( "bytes" "fmt" + "io" "regexp" + "strings" ) // Color colorizes your strings using the default settings. @@ -26,6 +28,15 @@ func Color(v string) string { return def.Color(v) } +// ColorPrefix returns the color sequence that prefixes the given text. +// +// This is useful when wrapping text if you want to inherit the color +// of the wrapped text. For example, "[green]foo" will return "[green]". +// If there is no color sequence, then this will return "". +func ColorPrefix(v string) string { + return def.ColorPrefix(v) +} + // Colorize colorizes your strings, giving you the ability to customize // some of the colorization process. // @@ -89,6 +100,15 @@ func (c *Colorize) Color(v string) string { return result.String() } +// ColorPrefix returns the first color sequence that exists in this string. +// +// For example: "[green]foo" would return "[green]". If no color sequence +// exists, then "" is returned. This is especially useful when wrapping +// colored texts to inherit the color of the wrapped text. +func (c *Colorize) ColorPrefix(v string) string { + return prefixRe.FindString(strings.TrimSpace(v)) +} + // DefaultColors are the default colors used when colorizing. // // If the color is surrounded in underscores, such as "_blue_", then that @@ -158,4 +178,67 @@ func init() { } var def Colorize -var parseRe = regexp.MustCompile(`(?i)\[[a-z0-9_-]+\]`) +var parseReRaw = `\[[a-z0-9_-]+\]` +var parseRe = regexp.MustCompile(`(?i)` + parseReRaw) +var prefixRe = regexp.MustCompile(`^(?i)(` + parseReRaw + `)+`) + +// Print is a convenience wrapper for fmt.Print with support for color codes. +// +// Print formats using the default formats for its operands and writes to +// standard output with support for color codes. Spaces are added between +// operands when neither is a string. It returns the number of bytes written +// and any write error encountered. +func Print(a string) (n int, err error) { + return fmt.Print(Color(a)) +} + +// Println is a convenience wrapper for fmt.Println with support for color +// codes. +// +// Println formats using the default formats for its operands and writes to +// standard output with support for color codes. Spaces are always added +// between operands and a newline is appended. It returns the number of bytes +// written and any write error encountered. +func Println(a string) (n int, err error) { + return fmt.Println(Color(a)) +} + +// Printf is a convenience wrapper for fmt.Printf with support for color codes. +// +// Printf formats according to a format specifier and writes to standard output +// with support for color codes. It returns the number of bytes written and any +// write error encountered. +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(Color(format), a...) +} + +// Fprint is a convenience wrapper for fmt.Fprint with support for color codes. +// +// Fprint formats using the default formats for its operands and writes to w +// with support for color codes. Spaces are added between operands when neither +// is a string. It returns the number of bytes written and any write error +// encountered. +func Fprint(w io.Writer, a string) (n int, err error) { + return fmt.Fprint(w, Color(a)) +} + +// Fprintln is a convenience wrapper for fmt.Fprintln with support for color +// codes. +// +// Fprintln formats using the default formats for its operands and writes to w +// with support for color codes. Spaces are always added between operands and a +// newline is appended. It returns the number of bytes written and any write +// error encountered. +func Fprintln(w io.Writer, a string) (n int, err error) { + return fmt.Fprintln(w, Color(a)) +} + +// Fprintf is a convenience wrapper for fmt.Fprintf with support for color +// codes. +// +// Fprintf formats according to a format specifier and writes to w with support +// for color codes. It returns the number of bytes written and any write error +// encountered. +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, Color(format), a...) +} diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/.travis.yml b/Godeps/_workspace/src/github.com/onsi/ginkgo/.travis.yml index f8b6984..f0e67b8 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/.travis.yml +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/.travis.yml @@ -1,12 +1,15 @@ language: go go: + - 1.3 - 1.4 + - 1.5 + - tip install: - - go get -v ./... + - go get -v -t ./... - go get golang.org/x/tools/cmd/cover - go get github.com/onsi/gomega - go install github.com/onsi/ginkgo/ginkgo - export PATH=$PATH:$HOME/gopath/bin -script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --failOnPending --randomizeSuites --race +script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/CHANGELOG.md b/Godeps/_workspace/src/github.com/onsi/ginkgo/CHANGELOG.md index 06c7428..438c8c1 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/CHANGELOG.md +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/CHANGELOG.md @@ -2,6 +2,27 @@ Improvements: +- `Skip(message)` can be used to skip the current test. +- Added `extensions/table` - a Ginkgo DSL for [Table Driven Tests](http://onsi.github.io/ginkgo/#table-driven-tests) + +Bug Fixes: + +- Ginkgo tests now fail when you `panic(nil)` (#167) + +## 1.2.0 5/31/2015 + +Improvements + +- `ginkgo -coverpkg` calls down to `go test -coverpkg` (#160) +- `ginkgo -afterSuiteHook COMMAND` invokes the passed-in `COMMAND` after a test suite completes (#152) +- Relaxed requirement for Go 1.4+. `ginkgo` now works with Go v1.3+ (#166) + +## 1.2.0-beta + +Ginkgo now requires Go 1.4+ + +Improvements: + - Call reporters in reverse order when announcing spec completion -- allows custom reporters to emit output before the default reporter does. - Improved focus behavior. Now, this: @@ -26,13 +47,18 @@ Improvements: - Support `bootstrap`ping and `generate`ing [Agouti](http://agouti.org) specs. - `ginkgo generate` and `ginkgo bootstrap` now honor the package name already defined in a given directory - The `ginkgo` CLI ignores `SIGQUIT`. Prevents its stack dump from interlacing with the underlying test suite's stack dump. +- The `ginkgo` CLI now compiles tests into a temporary directory instead of the package directory. This necessitates upgrading to Go v1.4+. +- `ginkgo -notify` now works on Linux Bug Fixes: - If --skipPackages is used and all packages are skipped, Ginkgo should exit 0. - Fix tempfile leak when running in parallel - Fix incorrect failure message when a panic occurs during a parallel test run - +- Fixed an issue where a pending test within a focused context (or a focused test within a pending context) would skip all other tests. +- Be more consistent about handling SIGTERM as well as SIGINT +- When interupted while concurrently compiling test suites in the background, Ginkgo now cleans up the compiled artifacts. +- Fixed a long standing bug where `ginkgo -p` would hang if a process spawned by one of the Ginkgo parallel nodes does not exit. (Hooray!) ## 1.1.0 (8/2/2014) diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/README.md b/Godeps/_workspace/src/github.com/onsi/ginkgo/README.md index 5cb6fdc..b8b77b5 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/README.md +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/README.md @@ -59,7 +59,7 @@ Agouti allows you run WebDriver integration tests. Learn more about Agouti [her ## Set Me Up! -You'll need Golang v1.2+ (Ubuntu users: you probably have Golang v1.0 -- you'll need to upgrade!) +You'll need Golang v1.3+ (Ubuntu users: you probably have Golang v1.0 -- you'll need to upgrade!) ```bash diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/config/config.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/config/config.go index aa4d8ed..46ce16a 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/config/config.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/config/config.go @@ -20,7 +20,7 @@ import ( "fmt" ) -const VERSION = "1.1.0" +const VERSION = "1.2.0" type GinkgoConfigType struct { RandomSeed int64 diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/extensions/table/table.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/extensions/table/table.go new file mode 100644 index 0000000..ae8ab7d --- /dev/null +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/extensions/table/table.go @@ -0,0 +1,98 @@ +/* + +Table provides a simple DSL for Ginkgo-native Table-Driven Tests + +The godoc documentation describes Table's API. More comprehensive documentation (with examples!) is available at http://onsi.github.io/ginkgo#table-driven-tests + +*/ + +package table + +import ( + "fmt" + "reflect" + + "github.com/onsi/ginkgo" +) + +/* +DescribeTable describes a table-driven test. + +For example: + + DescribeTable("a simple table", + func(x int, y int, expected bool) { + Ω(x > y).Should(Equal(expected)) + }, + Entry("x > y", 1, 0, true), + Entry("x == y", 0, 0, false), + Entry("x < y", 0, 1, false), + ) + +The first argument to `DescribeTable` is a string description. +The second argument is a function that will be run for each table entry. Your assertions go here - the function is equivalent to a Ginkgo It. +The subsequent arguments must be of type `TableEntry`. We recommend using the `Entry` convenience constructors. + +The `Entry` constructor takes a string description followed by an arbitrary set of parameters. These parameters are passed into your function. + +Under the hood, `DescribeTable` simply generates a new Ginkgo `Describe`. Each `Entry` is turned into an `It` within the `Describe`. + +It's important to understand that the `Describe`s and `It`s are generated at evaluation time (i.e. when Ginkgo constructs the tree of tests and before the tests run). + +Individual Entries can be focused (with FEntry) or marked pending (with PEntry or XEntry). In addition, the entire table can be focused or marked pending with FDescribeTable and PDescribeTable/XDescribeTable. +*/ +func DescribeTable(description string, itBody interface{}, entries ...TableEntry) bool { + describeTable(description, itBody, entries, false, false) + return true +} + +/* +You can focus a table with `FDescribeTable`. This is equivalent to `FDescribe`. +*/ +func FDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool { + describeTable(description, itBody, entries, false, true) + return true +} + +/* +You can mark a table as pending with `PDescribeTable`. This is equivalent to `PDescribe`. +*/ +func PDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool { + describeTable(description, itBody, entries, true, false) + return true +} + +/* +You can mark a table as pending with `XDescribeTable`. This is equivalent to `XDescribe`. +*/ +func XDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool { + describeTable(description, itBody, entries, true, false) + return true +} + +func describeTable(description string, itBody interface{}, entries []TableEntry, pending bool, focused bool) { + itBodyValue := reflect.ValueOf(itBody) + if itBodyValue.Kind() != reflect.Func { + panic(fmt.Sprintf("DescribeTable expects a function, got %#v", itBody)) + } + + if pending { + ginkgo.PDescribe(description, func() { + for _, entry := range entries { + entry.generateIt(itBodyValue) + } + }) + } else if focused { + ginkgo.FDescribe(description, func() { + for _, entry := range entries { + entry.generateIt(itBodyValue) + } + }) + } else { + ginkgo.Describe(description, func() { + for _, entry := range entries { + entry.generateIt(itBodyValue) + } + }) + } +} diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/extensions/table/table_entry.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/extensions/table/table_entry.go new file mode 100644 index 0000000..a6a9e3c --- /dev/null +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/extensions/table/table_entry.go @@ -0,0 +1,72 @@ +package table + +import ( + "reflect" + + "github.com/onsi/ginkgo" +) + +/* +TableEntry represents an entry in a table test. You generally use the `Entry` constructor. +*/ +type TableEntry struct { + Description string + Parameters []interface{} + Pending bool + Focused bool +} + +func (t TableEntry) generateIt(itBody reflect.Value) { + if t.Pending { + ginkgo.PIt(t.Description) + return + } + + values := []reflect.Value{} + for _, param := range t.Parameters { + values = append(values, reflect.ValueOf(param)) + } + + body := func() { + itBody.Call(values) + } + + if t.Focused { + ginkgo.FIt(t.Description, body) + } else { + ginkgo.It(t.Description, body) + } +} + +/* +Entry constructs a TableEntry. + +The first argument is a required description (this becomes the content of the generated Ginkgo `It`). +Subsequent parameters are saved off and sent to the callback passed in to `DescribeTable`. + +Each Entry ends up generating an individual Ginkgo It. +*/ +func Entry(description string, parameters ...interface{}) TableEntry { + return TableEntry{description, parameters, false, false} +} + +/* +You can focus a particular entry with FEntry. This is equivalent to FIt. +*/ +func FEntry(description string, parameters ...interface{}) TableEntry { + return TableEntry{description, parameters, false, true} +} + +/* +You can mark a particular entry as pending with PEntry. This is equivalent to PIt. +*/ +func PEntry(description string, parameters ...interface{}) TableEntry { + return TableEntry{description, parameters, true, false} +} + +/* +You can mark a particular entry as pending with XEntry. This is equivalent to XIt. +*/ +func XEntry(description string, parameters ...interface{}) TableEntry { + return TableEntry{description, parameters, true, false} +} diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/bootstrap_command.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/bootstrap_command.go index daade74..d804fe0 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/bootstrap_command.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/bootstrap_command.go @@ -54,7 +54,7 @@ var agoutiBootstrapText = `package {{.Package}}_test import ( {{.GinkgoImport}} {{.GomegaImport}} - . "github.com/sclevine/agouti/core" + "github.com/sclevine/agouti" "testing" ) @@ -64,23 +64,20 @@ func Test{{.FormattedName}}(t *testing.T) { RunSpecs(t, "{{.FormattedName}} Suite") } -var agoutiDriver WebDriver +var agoutiDriver *agouti.WebDriver var _ = BeforeSuite(func() { - var err error - // Choose a WebDriver: - agoutiDriver, err = PhantomJS() - // agoutiDriver, err = Selenium() - // agoutiDriver, err = Chrome() + agoutiDriver = agouti.PhantomJS() + // agoutiDriver = agouti.Selenium() + // agoutiDriver = agouti.ChromeDriver() - Expect(err).NotTo(HaveOccurred()) Expect(agoutiDriver.Start()).To(Succeed()) }) var _ = AfterSuite(func() { - agoutiDriver.Stop() + Expect(agoutiDriver.Stop()).To(Succeed()) }) ` diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/build_command.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/build_command.go index badae02..bbba8a1 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/build_command.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/build_command.go @@ -46,15 +46,19 @@ func (r *SpecBuilder) BuildSpecs(args []string, additionalArgs []string) { passed := true for _, suite := range suites { - runner := testrunner.New(suite, 1, false, r.commandFlags.Race, r.commandFlags.Cover, r.commandFlags.Tags, nil) + runner := testrunner.New(suite, 1, false, r.commandFlags.Race, r.commandFlags.Cover, r.commandFlags.CoverPkg, r.commandFlags.Tags, nil) fmt.Printf("Compiling %s...\n", suite.PackageName) - err := runner.Compile() + + path, _ := filepath.Abs(filepath.Join(suite.Path, fmt.Sprintf("%s.test", suite.PackageName))) + err := runner.CompileTo(path) if err != nil { fmt.Println(err.Error()) passed = false } else { - fmt.Printf(" compiled %s.test\n", filepath.Join(suite.Path, suite.PackageName)) + fmt.Printf(" compiled %s.test\n", suite.PackageName) } + + runner.CleanUp() } if passed { diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/generate_command.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/generate_command.go index ad25dd8..7dd3b4d 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/generate_command.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/generate_command.go @@ -51,21 +51,21 @@ import ( {{if .IncludeImports}}. "github.com/onsi/ginkgo"{{end}} {{if .IncludeImports}}. "github.com/onsi/gomega"{{end}} - . "github.com/sclevine/agouti/core" . "github.com/sclevine/agouti/matchers" + "github.com/sclevine/agouti" ) var _ = Describe("{{.Subject}}", func() { - var page Page + var page *agouti.Page BeforeEach(func() { var err error - page, err = agoutiDriver.Page() + page, err = agoutiDriver.NewPage() Expect(err).NotTo(HaveOccurred()) }) AfterEach(func() { - page.Destroy() + Expect(page.Destroy()).To(Succeed()) }) }) ` diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/interrupthandler/interrupt_handler.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/interrupthandler/interrupt_handler.go index 82e49ad..c15db0b 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/interrupthandler/interrupt_handler.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/interrupthandler/interrupt_handler.go @@ -4,6 +4,7 @@ import ( "os" "os/signal" "sync" + "syscall" ) type InterruptHandler struct { @@ -33,7 +34,7 @@ func (h *InterruptHandler) WasInterrupted() bool { func (h *InterruptHandler) handleInterrupt() { c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) <-c signal.Stop(c) diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/main.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/main.go index cf0cf35..b031b80 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/main.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/main.go @@ -58,7 +58,7 @@ passing `ginkgo watch` the `-r` flag will recursively detect all test suites und `watch` does not detect *new* packages. Moreover, changes in package X only rerun the tests for package X, tests for packages that depend on X are not rerun. -[OSX only] To receive (desktop) notifications when a test run completes: +[OSX & Linux only] To receive (desktop) notifications when a test run completes: ginkgo -notify diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/notifications.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/notifications.go index 642f12c..368d61f 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/notifications.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/notifications.go @@ -4,7 +4,11 @@ import ( "fmt" "os" "os/exec" + "regexp" + "runtime" + "strings" + "github.com/onsi/ginkgo/config" "github.com/onsi/ginkgo/ginkgo/testsuite" ) @@ -20,9 +24,15 @@ func NewNotifier(commandFlags *RunWatchAndBuildCommandFlags) *Notifier { func (n *Notifier) VerifyNotificationsAreAvailable() { if n.commandFlags.Notify { - _, err := exec.LookPath("terminal-notifier") - if err != nil { - fmt.Printf(`--notify requires terminal-notifier, which you don't seem to have installed. + onLinux := (runtime.GOOS == "linux") + onOSX := (runtime.GOOS == "darwin") + if onOSX { + + _, err := exec.LookPath("terminal-notifier") + if err != nil { + fmt.Printf(`--notify requires terminal-notifier, which you don't seem to have installed. + +OSX: To remedy this: @@ -32,7 +42,22 @@ To learn more about terminal-notifier: https://github.com/alloy/terminal-notifier `) - os.Exit(1) + os.Exit(1) + } + + } else if onLinux { + + _, err := exec.LookPath("notify-send") + if err != nil { + fmt.Printf(`--notify requires terminal-notifier or notify-send, which you don't seem to have installed. + +Linux: + +Download and install notify-send for your distribution +`) + os.Exit(1) + } + } } } @@ -46,16 +71,71 @@ func (n *Notifier) SendSuiteCompletionNotification(suite testsuite.TestSuite, su } func (n *Notifier) SendNotification(title string, subtitle string) { - args := []string{"-title", title, "-subtitle", subtitle, "-group", "com.onsi.ginkgo"} - - terminal := os.Getenv("TERM_PROGRAM") - if terminal == "iTerm.app" { - args = append(args, "-activate", "com.googlecode.iterm2") - } else if terminal == "Apple_Terminal" { - args = append(args, "-activate", "com.apple.Terminal") - } if n.commandFlags.Notify { - exec.Command("terminal-notifier", args...).Run() + onLinux := (runtime.GOOS == "linux") + onOSX := (runtime.GOOS == "darwin") + + if onOSX { + + _, err := exec.LookPath("terminal-notifier") + if err == nil { + args := []string{"-title", title, "-subtitle", subtitle, "-group", "com.onsi.ginkgo"} + terminal := os.Getenv("TERM_PROGRAM") + if terminal == "iTerm.app" { + args = append(args, "-activate", "com.googlecode.iterm2") + } else if terminal == "Apple_Terminal" { + args = append(args, "-activate", "com.apple.Terminal") + } + + exec.Command("terminal-notifier", args...).Run() + } + + } else if onLinux { + + _, err := exec.LookPath("notify-send") + if err == nil { + args := []string{"-a", "ginkgo", title, subtitle} + exec.Command("notify-send", args...).Run() + } + + } + } +} + +func (n *Notifier) RunCommand(suite testsuite.TestSuite, suitePassed bool) { + + command := n.commandFlags.AfterSuiteHook + if command != "" { + + // Allow for string replacement to pass input to the command + passed := "[FAIL]" + if suitePassed { + passed = "[PASS]" + } + command = strings.Replace(command, "(ginkgo-suite-passed)", passed, -1) + command = strings.Replace(command, "(ginkgo-suite-name)", suite.PackageName, -1) + + // Must break command into parts + splitArgs := regexp.MustCompile(`'.+'|".+"|\S+`) + parts := splitArgs.FindAllString(command, -1) + + output, err := exec.Command(parts[0], parts[1:]...).CombinedOutput() + if err != nil { + fmt.Println("Post-suite command failed:") + if config.DefaultReporterConfig.NoColor { + fmt.Printf("\t%s\n", output) + } else { + fmt.Printf("\t%s%s%s\n", redColor, string(output), defaultStyle) + } + n.SendNotification("Ginkgo [ERROR]", fmt.Sprintf(`After suite command "%s" failed`, n.commandFlags.AfterSuiteHook)) + } else { + fmt.Println("Post-suite command succeeded:") + if config.DefaultReporterConfig.NoColor { + fmt.Printf("\t%s\n", output) + } else { + fmt.Printf("\t%s%s%s\n", greenColor, string(output), defaultStyle) + } + } } } diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_command.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_command.go index c8caa99..c5cf277 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_command.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_command.go @@ -71,7 +71,7 @@ func (r *SpecRunner) RunSpecs(args []string, additionalArgs []string) { runners := []*testrunner.TestRunner{} for _, suite := range suites { - runners = append(runners, testrunner.New(suite, r.commandFlags.NumCPU, r.commandFlags.ParallelStream, r.commandFlags.Race, r.commandFlags.Cover, r.commandFlags.Tags, additionalArgs)) + runners = append(runners, testrunner.New(suite, r.commandFlags.NumCPU, r.commandFlags.ParallelStream, r.commandFlags.Race, r.commandFlags.Cover, r.commandFlags.CoverPkg, r.commandFlags.Tags, additionalArgs)) } numSuites := 0 diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_watch_and_build_command_flags.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_watch_and_build_command_flags.go index e0357c3..e6bcf36 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_watch_and_build_command_flags.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/run_watch_and_build_command_flags.go @@ -11,6 +11,7 @@ type RunWatchAndBuildCommandFlags struct { Recurse bool Race bool Cover bool + CoverPkg string SkipPackage string Tags string @@ -19,6 +20,7 @@ type RunWatchAndBuildCommandFlags struct { NumCompilers int ParallelStream bool Notify bool + AfterSuiteHook string AutoNodes bool //only for run command @@ -87,11 +89,11 @@ func (c *RunWatchAndBuildCommandFlags) computeNodes() { func (c *RunWatchAndBuildCommandFlags) flags(mode int) { onWindows := (runtime.GOOS == "windows") - onOSX := (runtime.GOOS == "darwin") c.FlagSet.BoolVar(&(c.Recurse), "r", false, "Find and run test suites under the current directory recursively") c.FlagSet.BoolVar(&(c.Race), "race", false, "Run tests with race detection enabled") c.FlagSet.BoolVar(&(c.Cover), "cover", false, "Run tests with coverage analysis, will generate coverage profiles with the package name in the current directory") + c.FlagSet.StringVar(&(c.CoverPkg), "coverpkg", "", "Run tests with coverage on the given external modules") c.FlagSet.StringVar(&(c.SkipPackage), "skipPackage", "", "A comma-separated list of package names to be skipped. If any part of the package's path matches, that package is ignored.") c.FlagSet.StringVar(&(c.Tags), "tags", "", "A list of build tags to consider satisfied during the build") @@ -101,9 +103,10 @@ func (c *RunWatchAndBuildCommandFlags) flags(mode int) { c.FlagSet.IntVar(&(c.NumCompilers), "compilers", 0, "The number of concurrent compilations to run (0 will autodetect)") c.FlagSet.BoolVar(&(c.AutoNodes), "p", false, "Run in parallel with auto-detected number of nodes") c.FlagSet.BoolVar(&(c.ParallelStream), "stream", onWindows, "stream parallel test output in real time: less coherent, but useful for debugging") - if onOSX { + if !onWindows { c.FlagSet.BoolVar(&(c.Notify), "notify", false, "Send desktop notifications when a test run completes") } + c.FlagSet.StringVar(&(c.AfterSuiteHook), "afterSuiteHook", "", "Run a command when a suite test run completes") } if mode == runMode { diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/suite_runner.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/suite_runner.go index 28daf2e..7d56e5f 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/suite_runner.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/suite_runner.go @@ -3,6 +3,7 @@ package main import ( "fmt" "runtime" + "sync" "github.com/onsi/ginkgo/config" "github.com/onsi/ginkgo/ginkgo/interrupthandler" @@ -10,28 +11,21 @@ import ( "github.com/onsi/ginkgo/ginkgo/testsuite" ) +type compilationInput struct { + runner *testrunner.TestRunner + result chan compilationOutput +} + +type compilationOutput struct { + runner *testrunner.TestRunner + err error +} + type SuiteRunner struct { notifier *Notifier interruptHandler *interrupthandler.InterruptHandler } -type compiler struct { - runner *testrunner.TestRunner - compilationError chan error -} - -func (c *compiler) compile() { - retries := 0 - - err := c.runner.Compile() - for err != nil && retries < 5 { //We retry because Go sometimes steps on itself when multiple compiles happen in parallel. This is ugly, but should help resolve flakiness... - err = c.runner.Compile() - retries++ - } - - c.compilationError <- err -} - func NewSuiteRunner(notifier *Notifier, interruptHandler *interrupthandler.InterruptHandler) *SuiteRunner { return &SuiteRunner{ notifier: notifier, @@ -39,63 +33,111 @@ func NewSuiteRunner(notifier *Notifier, interruptHandler *interrupthandler.Inter } } -func (r *SuiteRunner) RunSuites(runners []*testrunner.TestRunner, numCompilers int, keepGoing bool, willCompile func(suite testsuite.TestSuite)) (testrunner.RunResult, int) { - runResult := testrunner.PassingRunResult() +func (r *SuiteRunner) compileInParallel(runners []*testrunner.TestRunner, numCompilers int, willCompile func(suite testsuite.TestSuite)) chan compilationOutput { + //we return this to the consumer, it will return each runner in order as it compiles + compilationOutputs := make(chan compilationOutput, len(runners)) - compilers := make([]*compiler, len(runners)) - for i, runner := range runners { - compilers[i] = &compiler{ - runner: runner, - compilationError: make(chan error, 1), - } + //an array of channels - the nth runner's compilation output is sent to the nth channel in this array + //we read from these channels in order to ensure we run the suites in order + orderedCompilationOutputs := []chan compilationOutput{} + for _ = range runners { + orderedCompilationOutputs = append(orderedCompilationOutputs, make(chan compilationOutput, 1)) } - compilerChannel := make(chan *compiler) + //we're going to spin up numCompilers compilers - they're going to run concurrently and will consume this channel + //we prefill the channel then close it, this ensures we compile things in the correct order + workPool := make(chan compilationInput, len(runners)) + for i, runner := range runners { + workPool <- compilationInput{runner, orderedCompilationOutputs[i]} + } + close(workPool) + + //pick a reasonable numCompilers if numCompilers == 0 { numCompilers = runtime.NumCPU() } + + //a WaitGroup to help us wait for all compilers to shut down + wg := &sync.WaitGroup{} + wg.Add(numCompilers) + + //spin up the concurrent compilers for i := 0; i < numCompilers; i++ { go func() { - for compiler := range compilerChannel { - if willCompile != nil { - willCompile(compiler.runner.Suite) + defer wg.Done() + for input := range workPool { + if r.interruptHandler.WasInterrupted() { + return } - compiler.compile() + + if willCompile != nil { + willCompile(input.runner.Suite) + } + + //We retry because Go sometimes steps on itself when multiple compiles happen in parallel. This is ugly, but should help resolve flakiness... + var err error + retries := 0 + for retries <= 5 { + if r.interruptHandler.WasInterrupted() { + return + } + if err = input.runner.Compile(); err == nil { + break + } + retries++ + } + + input.result <- compilationOutput{input.runner, err} } }() } + + //read from the compilation output channels *in order* and send them to the caller + //close the compilationOutputs channel to tell the caller we're done go func() { - for _, compiler := range compilers { - compilerChannel <- compiler + defer close(compilationOutputs) + for _, orderedCompilationOutput := range orderedCompilationOutputs { + select { + case compilationOutput := <-orderedCompilationOutput: + compilationOutputs <- compilationOutput + case <-r.interruptHandler.C: + //interrupt detected, wait for the compilers to shut down then bail + //this ensure we clean up after ourselves as we don't leave any compilation processes running + wg.Wait() + return + } } - close(compilerChannel) }() + return compilationOutputs +} + +func (r *SuiteRunner) RunSuites(runners []*testrunner.TestRunner, numCompilers int, keepGoing bool, willCompile func(suite testsuite.TestSuite)) (testrunner.RunResult, int) { + runResult := testrunner.PassingRunResult() + + compilationOutputs := r.compileInParallel(runners, numCompilers, willCompile) + numSuitesThatRan := 0 suitesThatFailed := []testsuite.TestSuite{} - for i, runner := range runners { - if r.interruptHandler.WasInterrupted() { - break - } - - compilationError := <-compilers[i].compilationError - if compilationError != nil { - fmt.Print(compilationError.Error()) + for compilationOutput := range compilationOutputs { + if compilationOutput.err != nil { + fmt.Print(compilationOutput.err.Error()) } numSuitesThatRan++ suiteRunResult := testrunner.FailingRunResult() - if compilationError == nil { - suiteRunResult = compilers[i].runner.Run() + if compilationOutput.err == nil { + suiteRunResult = compilationOutput.runner.Run() } - r.notifier.SendSuiteCompletionNotification(runner.Suite, suiteRunResult.Passed) + r.notifier.SendSuiteCompletionNotification(compilationOutput.runner.Suite, suiteRunResult.Passed) + r.notifier.RunCommand(compilationOutput.runner.Suite, suiteRunResult.Passed) runResult = runResult.Merge(suiteRunResult) if !suiteRunResult.Passed { - suitesThatFailed = append(suitesThatFailed, runner.Suite) + suitesThatFailed = append(suitesThatFailed, compilationOutput.runner.Suite) if !keepGoing { break } } - if i < len(runners)-1 && !config.DefaultReporterConfig.Succinct { + if numSuitesThatRan < len(runners) && !config.DefaultReporterConfig.Succinct { fmt.Println("") } } diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/testrunner/test_runner.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/testrunner/test_runner.go index e1a8098..a1e47ba 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/testrunner/test_runner.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/testrunner/test_runner.go @@ -22,30 +22,48 @@ import ( ) type TestRunner struct { - Suite testsuite.TestSuite - compiled bool + Suite testsuite.TestSuite + + compiled bool + compilationTargetPath string numCPU int parallelStream bool race bool cover bool + coverPkg string tags string additionalArgs []string } -func New(suite testsuite.TestSuite, numCPU int, parallelStream bool, race bool, cover bool, tags string, additionalArgs []string) *TestRunner { - return &TestRunner{ +func New(suite testsuite.TestSuite, numCPU int, parallelStream bool, race bool, cover bool, coverPkg string, tags string, additionalArgs []string) *TestRunner { + runner := &TestRunner{ Suite: suite, numCPU: numCPU, parallelStream: parallelStream, race: race, cover: cover, + coverPkg: coverPkg, tags: tags, additionalArgs: additionalArgs, } + + if !suite.Precompiled { + dir, err := ioutil.TempDir("", "ginkgo") + if err != nil { + panic(fmt.Sprintf("coulnd't create temporary directory... might be time to rm -rf:\n%s", err.Error())) + } + runner.compilationTargetPath = filepath.Join(dir, suite.PackageName+".test") + } + + return runner } func (t *TestRunner) Compile() error { + return t.CompileTo(t.compilationTargetPath) +} + +func (t *TestRunner) CompileTo(path string) error { if t.compiled { return nil } @@ -54,15 +72,16 @@ func (t *TestRunner) Compile() error { return nil } - os.Remove(t.compiledArtifact()) - - args := []string{"test", "-c", "-i"} + args := []string{"test", "-c", "-i", "-o", path} if t.race { args = append(args, "-race") } - if t.cover { + if t.cover || t.coverPkg != "" { args = append(args, "-cover", "-covermode=atomic") } + if t.coverPkg != "" { + args = append(args, fmt.Sprintf("-coverpkg=%s", t.coverPkg)) + } if t.tags != "" { args = append(args, fmt.Sprintf("-tags=%s", t.tags)) } @@ -78,13 +97,81 @@ func (t *TestRunner) Compile() error { if len(output) > 0 { return fmt.Errorf("Failed to compile %s:\n\n%s", t.Suite.PackageName, fixedOutput) } - return fmt.Errorf("") + return fmt.Errorf("Failed to compile %s", t.Suite.PackageName) + } + + if fileExists(path) == false { + compiledFile := filepath.Join(t.Suite.Path, t.Suite.PackageName+".test") + if fileExists(compiledFile) { + // seems like we are on an old go version that does not support the -o flag on go test + // move the compiled test file to the desired location by hand + err = os.Rename(compiledFile, path) + if err != nil { + // We cannot move the file, perhaps because the source and destination + // are on different partitions. We can copy the file, however. + err = copyFile(compiledFile, path) + if err != nil { + return fmt.Errorf("Failed to copy compiled file: %s", err) + } + } + } else { + return fmt.Errorf("Failed to compile %s: output file %q could not be found", t.Suite.PackageName, path) + } } t.compiled = true + return nil } +func fileExists(path string) bool { + _, err := os.Stat(path) + return err == nil || os.IsNotExist(err) == false +} + +// copyFile copies the contents of the file named src to the file named +// by dst. The file will be created if it does not already exist. If the +// destination file exists, all it's contents will be replaced by the contents +// of the source file. +func copyFile(src, dst string) error { + srcInfo, err := os.Stat(src) + if err != nil { + return err + } + mode := srcInfo.Mode() + + in, err := os.Open(src) + if err != nil { + return err + } + + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + + defer func() { + closeErr := out.Close() + if err == nil { + err = closeErr + } + }() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + + err = out.Sync() + if err != nil { + return err + } + + return out.Chmod(mode) +} + /* go test -c -i spits package.test out into the cwd. there's no way to change this. @@ -134,12 +221,7 @@ func (t *TestRunner) CleanUp() { if t.Suite.Precompiled { return } - os.Remove(t.compiledArtifact()) -} - -func (t *TestRunner) compiledArtifact() string { - compiledArtifact, _ := filepath.Abs(filepath.Join(t.Suite.Path, fmt.Sprintf("%s.test", t.Suite.PackageName))) - return compiledArtifact + os.RemoveAll(filepath.Dir(t.compilationTargetPath)) } func (t *TestRunner) runSerialGinkgoSuite() RunResult { @@ -196,7 +278,7 @@ func (t *TestRunner) runAndStreamParallelGinkgoSuite() RunResult { os.Stdout.Sync() - if t.cover { + if t.cover || t.coverPkg != "" { t.combineCoverprofiles() } @@ -257,21 +339,16 @@ func (t *TestRunner) runParallelGinkgoSuite() RunResult { fmt.Println("") case <-time.After(time.Second): //the aggregator never got back to us! something must have gone wrong - fmt.Println("") - fmt.Println("") - fmt.Println(" ----------------------------------------------------------- ") - fmt.Println(" | |") - fmt.Println(" | Ginkgo timed out waiting for all parallel nodes to end! |") - fmt.Println(" | Here is some salvaged output: |") - fmt.Println(" | |") - fmt.Println(" ----------------------------------------------------------- ") - fmt.Println("") - fmt.Println("") + fmt.Println(` + ------------------------------------------------------------------- + | | + | Ginkgo timed out waiting for all parallel nodes to report back! | + | | + ------------------------------------------------------------------- +`) os.Stdout.Sync() - time.Sleep(time.Second) - for _, writer := range writers { writer.Close() } @@ -283,7 +360,7 @@ func (t *TestRunner) runParallelGinkgoSuite() RunResult { os.Stdout.Sync() } - if t.cover { + if t.cover || t.coverPkg != "" { t.combineCoverprofiles() } @@ -291,8 +368,8 @@ func (t *TestRunner) runParallelGinkgoSuite() RunResult { } func (t *TestRunner) cmd(ginkgoArgs []string, stream io.Writer, node int) *exec.Cmd { - args := []string{"-test.timeout=24h"} - if t.cover { + args := []string{"--test.timeout=24h"} + if t.cover || t.coverPkg != "" { coverprofile := "--test.coverprofile=" + t.Suite.PackageName + ".coverprofile" if t.numCPU > 1 { coverprofile = fmt.Sprintf("%s.%d", coverprofile, node) @@ -303,7 +380,12 @@ func (t *TestRunner) cmd(ginkgoArgs []string, stream io.Writer, node int) *exec. args = append(args, ginkgoArgs...) args = append(args, t.additionalArgs...) - cmd := exec.Command(t.compiledArtifact(), args...) + path := t.compilationTargetPath + if t.Suite.Precompiled { + path, _ = filepath.Abs(filepath.Join(t.Suite.Path, fmt.Sprintf("%s.test", t.Suite.PackageName))) + } + + cmd := exec.Command(path, args...) cmd.Dir = t.Suite.Path cmd.Stderr = stream diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/watch_command.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/watch_command.go index 02e89f1..03ea012 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/watch_command.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo/watch_command.go @@ -57,7 +57,7 @@ func (w *SpecWatcher) runnersForSuites(suites []testsuite.TestSuite, additionalA runners := []*testrunner.TestRunner{} for _, suite := range suites { - runners = append(runners, testrunner.New(suite, w.commandFlags.NumCPU, w.commandFlags.ParallelStream, w.commandFlags.Race, w.commandFlags.Cover, w.commandFlags.Tags, additionalArgs)) + runners = append(runners, testrunner.New(suite, w.commandFlags.NumCPU, w.commandFlags.ParallelStream, w.commandFlags.Race, w.commandFlags.Cover, w.commandFlags.CoverPkg, w.commandFlags.Tags, additionalArgs)) } return runners @@ -80,7 +80,7 @@ func (w *SpecWatcher) WatchSuites(args []string, additionalArgs []string) { } for suite, err := range errors { - fmt.Printf("Failed to watch %s: %s\n"+suite.PackageName, err) + fmt.Printf("Failed to watch %s: %s\n", suite.PackageName, err) } if len(suites) == 1 { diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo_dsl.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo_dsl.go index 1a31473..36f6d8e 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo_dsl.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/ginkgo_dsl.go @@ -130,6 +130,7 @@ type Done chan<- interface{} // IsMeasurement: true if the current test is a measurement // FileName: the name of the file containing the current test // LineNumber: the line number for the current test +// Failed: if the current test has failed, this will be true (useful in an AfterEach) type GinkgoTestDescription struct { FullTestText string ComponentTexts []string @@ -139,6 +140,8 @@ type GinkgoTestDescription struct { FileName string LineNumber int + + Failed bool } //CurrentGinkgoTestDescripton returns information about the current running test. @@ -157,6 +160,7 @@ func CurrentGinkgoTestDescription() GinkgoTestDescription { IsMeasurement: summary.IsMeasurement, FileName: subjectCodeLocation.FileName, LineNumber: subjectCodeLocation.LineNumber, + Failed: summary.HasFailureState(), } } @@ -218,6 +222,17 @@ func buildDefaultReporter() Reporter { } } +//Skip notifies Ginkgo that the current spec should be skipped. +func Skip(message string, callerSkip ...int) { + skip := 0 + if len(callerSkip) > 0 { + skip = callerSkip[0] + } + + globalFailer.Skip(message, codelocation.New(skip+1)) + panic(GINKGO_PANIC) +} + //Fail notifies Ginkgo that the current spec has failed. (Gomega will call Fail for you automatically when an assertion fails.) func Fail(message string, callerSkip ...int) { skip := 0 diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/failer/failer.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/failer/failer.go index 4019666..678ea25 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/failer/failer.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/failer/failer.go @@ -77,3 +77,16 @@ func (f *Failer) Drain(componentType types.SpecComponentType, componentIndex int return failure, outcome } + +func (f *Failer) Skip(message string, location types.CodeLocation) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.state == types.SpecStatePassed { + f.state = types.SpecStateSkipped + f.failure = types.SpecFailure{ + Message: message, + Location: location, + } + } +} diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/leafnodes/runner.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/leafnodes/runner.go index 04ec6db..003f851 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/leafnodes/runner.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/leafnodes/runner.go @@ -68,8 +68,10 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) done := make(chan interface{}, 1) go func() { + finished := false + defer func() { - if e := recover(); e != nil { + if e := recover(); e != nil || !finished { r.failer.Panic(codelocation.New(2), e) select { case <-done: @@ -81,6 +83,7 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) }() r.asyncFunc(done) + finished = true }() select { @@ -93,8 +96,10 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) return } func (r *runner) runSync() (outcome types.SpecState, failure types.SpecFailure) { + finished := false + defer func() { - if e := recover(); e != nil { + if e := recover(); e != nil || !finished { r.failer.Panic(codelocation.New(2), e) } @@ -102,6 +107,7 @@ func (r *runner) runSync() (outcome types.SpecState, failure types.SpecFailure) }() r.syncFunc() + finished = true return } diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/aggregator.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/aggregator.go index 9dcfb5f..1e34dbf 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/aggregator.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/aggregator.go @@ -209,7 +209,7 @@ func (aggregator *Aggregator) announceSpec(specSummary *types.SpecSummary) { case types.SpecStatePending: aggregator.stenographer.AnnouncePendingSpec(specSummary, aggregator.config.NoisyPendings && !aggregator.config.Succinct) case types.SpecStateSkipped: - aggregator.stenographer.AnnounceSkippedSpec(specSummary) + aggregator.stenographer.AnnounceSkippedSpec(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace) case types.SpecStateTimedOut: aggregator.stenographer.AnnounceSpecTimedOut(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace) case types.SpecStatePanicked: diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go index 8304cf5..181b227 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go @@ -14,10 +14,8 @@ func NewOutputInterceptor() OutputInterceptor { } type outputInterceptor struct { - stdoutPlaceholder *os.File - stderrPlaceholder *os.File - redirectFile *os.File - intercepting bool + redirectFile *os.File + intercepting bool } func (interceptor *outputInterceptor) StartInterceptingOutput() error { @@ -33,19 +31,6 @@ func (interceptor *outputInterceptor) StartInterceptingOutput() error { return err } - interceptor.stdoutPlaceholder, err = ioutil.TempFile("", "ginkgo-output") - if err != nil { - return err - } - - interceptor.stderrPlaceholder, err = ioutil.TempFile("", "ginkgo-output") - if err != nil { - return err - } - - syscall.Dup2(1, int(interceptor.stdoutPlaceholder.Fd())) - syscall.Dup2(2, int(interceptor.stderrPlaceholder.Fd())) - syscall.Dup2(int(interceptor.redirectFile.Fd()), 1) syscall.Dup2(int(interceptor.redirectFile.Fd()), 2) @@ -57,18 +42,9 @@ func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, return "", errors.New("Not intercepting output!") } - syscall.Dup2(int(interceptor.stdoutPlaceholder.Fd()), 1) - syscall.Dup2(int(interceptor.stderrPlaceholder.Fd()), 2) - - for _, f := range []*os.File{interceptor.redirectFile, interceptor.stdoutPlaceholder, interceptor.stderrPlaceholder} { - f.Close() - } - + interceptor.redirectFile.Close() output, err := ioutil.ReadFile(interceptor.redirectFile.Name()) - - for _, f := range []*os.File{interceptor.redirectFile, interceptor.stdoutPlaceholder, interceptor.stderrPlaceholder} { - os.Remove(f.Name()) - } + os.Remove(interceptor.redirectFile.Name()) interceptor.intercepting = false diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/spec.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/spec.go index 076fff1..ef788b7 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/spec.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/spec.go @@ -115,7 +115,7 @@ func (spec *Spec) Run(writer io.Writer) { }() for sample := 0; sample < spec.subject.Samples(); sample++ { - spec.state, spec.failure = spec.runSample(sample, writer) + spec.runSample(sample, writer) if spec.state != types.SpecStatePassed { return @@ -123,9 +123,9 @@ func (spec *Spec) Run(writer io.Writer) { } } -func (spec *Spec) runSample(sample int, writer io.Writer) (specState types.SpecState, specFailure types.SpecFailure) { - specState = types.SpecStatePassed - specFailure = types.SpecFailure{} +func (spec *Spec) runSample(sample int, writer io.Writer) { + spec.state = types.SpecStatePassed + spec.failure = types.SpecFailure{} innerMostContainerIndexToUnwind := -1 defer func() { @@ -134,9 +134,9 @@ func (spec *Spec) runSample(sample int, writer io.Writer) (specState types.SpecS for _, afterEach := range container.SetupNodesOfType(types.SpecComponentTypeAfterEach) { spec.announceSetupNode(writer, "AfterEach", container, afterEach) afterEachState, afterEachFailure := afterEach.Run() - if afterEachState != types.SpecStatePassed && specState == types.SpecStatePassed { - specState = afterEachState - specFailure = afterEachFailure + if afterEachState != types.SpecStatePassed && spec.state == types.SpecStatePassed { + spec.state = afterEachState + spec.failure = afterEachFailure } } } @@ -146,8 +146,8 @@ func (spec *Spec) runSample(sample int, writer io.Writer) (specState types.SpecS innerMostContainerIndexToUnwind = i for _, beforeEach := range container.SetupNodesOfType(types.SpecComponentTypeBeforeEach) { spec.announceSetupNode(writer, "BeforeEach", container, beforeEach) - specState, specFailure = beforeEach.Run() - if specState != types.SpecStatePassed { + spec.state, spec.failure = beforeEach.Run() + if spec.state != types.SpecStatePassed { return } } @@ -156,17 +156,15 @@ func (spec *Spec) runSample(sample int, writer io.Writer) (specState types.SpecS for _, container := range spec.containers { for _, justBeforeEach := range container.SetupNodesOfType(types.SpecComponentTypeJustBeforeEach) { spec.announceSetupNode(writer, "JustBeforeEach", container, justBeforeEach) - specState, specFailure = justBeforeEach.Run() - if specState != types.SpecStatePassed { + spec.state, spec.failure = justBeforeEach.Run() + if spec.state != types.SpecStatePassed { return } } } spec.announceSubject(writer, spec.subject) - specState, specFailure = spec.subject.Run() - - return + spec.state, spec.failure = spec.subject.Run() } func (spec *Spec) announceSetupNode(writer io.Writer, nodeType string, container *containernode.ContainerNode, setupNode leafnodes.BasicNode) { diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/specs.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/specs.go index a3d5451..9c671e3 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/specs.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/spec/specs.go @@ -52,7 +52,7 @@ func (e *Specs) ApplyFocus(description string, focusString string, skipString st func (e *Specs) applyProgrammaticFocus() { e.hasProgrammaticFocus = false for _, spec := range e.specs { - if spec.Focused() { + if spec.Focused() && !spec.Pending() { e.hasProgrammaticFocus = true break } diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go index 123fdae..7ca7740 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go @@ -170,7 +170,7 @@ func (runner *SpecRunner) CurrentSpecSummary() (*types.SpecSummary, bool) { func (runner *SpecRunner) registerForInterrupts() { c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) <-c signal.Stop(c) diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/default_reporter.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/default_reporter.go index 45a44de..044d2df 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/default_reporter.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/default_reporter.go @@ -65,7 +65,7 @@ func (reporter *DefaultReporter) SpecDidComplete(specSummary *types.SpecSummary) case types.SpecStatePending: reporter.stenographer.AnnouncePendingSpec(specSummary, reporter.config.NoisyPendings && !reporter.config.Succinct) case types.SpecStateSkipped: - reporter.stenographer.AnnounceSkippedSpec(specSummary) + reporter.stenographer.AnnounceSkippedSpec(specSummary, reporter.config.Succinct, reporter.config.FullTrace) case types.SpecStateTimedOut: reporter.stenographer.AnnounceSpecTimedOut(specSummary, reporter.config.Succinct, reporter.config.FullTrace) case types.SpecStatePanicked: diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/fake_stenographer.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/fake_stenographer.go index 3a1e0c2..1ff6104 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/fake_stenographer.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/fake_stenographer.go @@ -117,8 +117,8 @@ func (stenographer *FakeStenographer) AnnouncePendingSpec(spec *types.SpecSummar stenographer.registerCall("AnnouncePendingSpec", spec, noisy) } -func (stenographer *FakeStenographer) AnnounceSkippedSpec(spec *types.SpecSummary) { - stenographer.registerCall("AnnounceSkippedSpec", spec) +func (stenographer *FakeStenographer) AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool) { + stenographer.registerCall("AnnounceSkippedSpec", spec, succinct, fullTrace) } func (stenographer *FakeStenographer) AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool) { diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go index d82cdb2..eeb5cbb 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go @@ -49,7 +49,7 @@ type Stenographer interface { AnnounceSuccesfulMeasurement(spec *types.SpecSummary, succinct bool) AnnouncePendingSpec(spec *types.SpecSummary, noisy bool) - AnnounceSkippedSpec(spec *types.SpecSummary) + AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool) AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool) AnnounceSpecPanicked(spec *types.SpecSummary, succinct bool, fullTrace bool) @@ -197,7 +197,7 @@ func (s *consoleStenographer) announceSetupFailure(name string, summary *types.S s.println(0, s.colorize(redColor+boldStyle, "%s [%.3f seconds]", message, summary.RunTime.Seconds())) - indentation := s.printCodeLocationBlock([]string{name}, []types.CodeLocation{summary.CodeLocation}, summary.ComponentType, 0, true, true) + indentation := s.printCodeLocationBlock([]string{name}, []types.CodeLocation{summary.CodeLocation}, summary.ComponentType, 0, summary.State, true) s.printNewLine() s.printFailure(indentation, summary.State, summary.Failure, fullTrace) @@ -252,9 +252,21 @@ func (s *consoleStenographer) AnnouncePendingSpec(spec *types.SpecSummary, noisy } } -func (s *consoleStenographer) AnnounceSkippedSpec(spec *types.SpecSummary) { - s.print(0, s.colorize(cyanColor, "S")) - s.stream() +func (s *consoleStenographer) AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool) { + // Skips at runtime will have a non-empty spec.Failure. All others should be succinct. + if succinct || spec.Failure == (types.SpecFailure{}) { + s.print(0, s.colorize(cyanColor, "S")) + s.stream() + } else { + s.startBlock() + s.println(0, s.colorize(cyanColor+boldStyle, "S [SKIPPING]%s [%.3f seconds]", s.failureContext(spec.Failure.ComponentType), spec.RunTime.Seconds())) + + indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, spec.State, succinct) + + s.printNewLine() + s.printSkip(indentation, spec.Failure) + s.endBlock() + } } func (s *consoleStenographer) AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool) { @@ -299,7 +311,7 @@ func (s *consoleStenographer) SummarizeFailures(summaries []*types.SpecSummary) } else if summary.Failed() { s.print(0, s.colorize(redColor+boldStyle, "[Fail] ")) } - s.printSpecContext(summary.ComponentTexts, summary.ComponentCodeLocations, summary.Failure.ComponentType, summary.Failure.ComponentIndex, true, true) + s.printSpecContext(summary.ComponentTexts, summary.ComponentCodeLocations, summary.Failure.ComponentType, summary.Failure.ComponentIndex, summary.State, true) s.printNewLine() s.println(0, s.colorize(lightGrayColor, summary.Failure.Location.String())) } @@ -332,7 +344,7 @@ func (s *consoleStenographer) printBlockWithMessage(header string, message strin s.startBlock() s.println(0, header) - indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, types.SpecComponentTypeInvalid, 0, false, succinct) + indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, types.SpecComponentTypeInvalid, 0, spec.State, succinct) if message != "" { s.printNewLine() @@ -346,7 +358,7 @@ func (s *consoleStenographer) printSpecFailure(message string, spec *types.SpecS s.startBlock() s.println(0, s.colorize(redColor+boldStyle, "%s%s [%.3f seconds]", message, s.failureContext(spec.Failure.ComponentType), spec.RunTime.Seconds())) - indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, true, succinct) + indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, spec.State, succinct) s.printNewLine() s.printFailure(indentation, spec.State, spec.Failure, fullTrace) @@ -370,6 +382,12 @@ func (s *consoleStenographer) failureContext(failedComponentType types.SpecCompo return "" } +func (s *consoleStenographer) printSkip(indentation int, spec types.SpecFailure) { + s.println(indentation, s.colorize(cyanColor, spec.Message)) + s.printNewLine() + s.println(indentation, spec.Location.String()) +} + func (s *consoleStenographer) printFailure(indentation int, state types.SpecState, failure types.SpecFailure, fullTrace bool) { if state == types.SpecStatePanicked { s.println(indentation, s.colorize(redColor+boldStyle, failure.Message)) @@ -390,7 +408,7 @@ func (s *consoleStenographer) printFailure(indentation int, state types.SpecStat } } -func (s *consoleStenographer) printSpecContext(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, failure bool, succinct bool) int { +func (s *consoleStenographer) printSpecContext(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, state types.SpecState, succinct bool) int { startIndex := 1 indentation := 0 @@ -399,7 +417,11 @@ func (s *consoleStenographer) printSpecContext(componentTexts []string, componen } for i := startIndex; i < len(componentTexts); i++ { - if failure && i == failedComponentIndex { + if (state.IsFailure() || state == types.SpecStateSkipped) && i == failedComponentIndex { + color := redColor + if state == types.SpecStateSkipped { + color = cyanColor + } blockType := "" switch failedComponentType { case types.SpecComponentTypeBeforeSuite: @@ -418,9 +440,9 @@ func (s *consoleStenographer) printSpecContext(componentTexts []string, componen blockType = "Measurement" } if succinct { - s.print(0, s.colorize(redColor+boldStyle, "[%s] %s ", blockType, componentTexts[i])) + s.print(0, s.colorize(color+boldStyle, "[%s] %s ", blockType, componentTexts[i])) } else { - s.println(indentation, s.colorize(redColor+boldStyle, "%s [%s]", componentTexts[i], blockType)) + s.println(indentation, s.colorize(color+boldStyle, "%s [%s]", componentTexts[i], blockType)) s.println(indentation, s.colorize(grayColor, "%s", componentCodeLocations[i])) } } else { @@ -437,8 +459,8 @@ func (s *consoleStenographer) printSpecContext(componentTexts []string, componen return indentation } -func (s *consoleStenographer) printCodeLocationBlock(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, failure bool, succinct bool) int { - indentation := s.printSpecContext(componentTexts, componentCodeLocations, failedComponentType, failedComponentIndex, failure, succinct) +func (s *consoleStenographer) printCodeLocationBlock(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, state types.SpecState, succinct bool) int { + indentation := s.printSpecContext(componentTexts, componentCodeLocations, failedComponentType, failedComponentIndex, state, succinct) if succinct { if len(componentTexts) > 0 { diff --git a/Godeps/_workspace/src/github.com/onsi/ginkgo/types/types.go b/Godeps/_workspace/src/github.com/onsi/ginkgo/types/types.go index 583b347..889612e 100644 --- a/Godeps/_workspace/src/github.com/onsi/ginkgo/types/types.go +++ b/Godeps/_workspace/src/github.com/onsi/ginkgo/types/types.go @@ -35,7 +35,7 @@ type SpecSummary struct { } func (s SpecSummary) HasFailureState() bool { - return s.State == SpecStateTimedOut || s.State == SpecStatePanicked || s.State == SpecStateFailed + return s.State.IsFailure() } func (s SpecSummary) TimedOut() bool { @@ -115,6 +115,10 @@ const ( SpecStateTimedOut ) +func (state SpecState) IsFailure() bool { + return state == SpecStateTimedOut || state == SpecStatePanicked || state == SpecStateFailed +} + type SpecComponentType uint const ( diff --git a/Godeps/_workspace/src/github.com/zachgersh/go-github/LICENSE b/Godeps/_workspace/src/github.com/zachgersh/go-github/LICENSE new file mode 100644 index 0000000..3a3a8ec --- /dev/null +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/LICENSE @@ -0,0 +1,340 @@ +Copyright (c) 2013 The go-github AUTHORS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT +OWNER 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. + +---------- + +Some documentation is taken from the GitHub Developer site +, which is available under a Creative Commons +Attribution 3.0 License: + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(f) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined above) for the purposes of this + License. + c. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + d. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + e. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + f. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + g. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + h. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + i. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor waives the + exclusive right to collect such royalties for any exercise by You + of the rights granted under this License; and, + iii. Voluntary License Schemes. The Licensor waives the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(b), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(b), as requested. + b. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and (iv) , consistent with Section 3(b), in the case of an Adaptation, + a credit identifying the use of the Work in the Adaptation (e.g., + "French translation of the Work by Original Author," or "Screenplay + based on original Work by Original Author"). The credit required by + this Section 4 (b) may be implemented in any reasonable manner; + provided, however, that in the case of a Adaptation or Collection, at + a minimum such credit will appear, if a credit for all contributing + authors of the Adaptation or Collection appears, then as part of these + credits and in a manner at least as prominent as the credits for the + other contributing authors. For the avoidance of doubt, You may only + use the credit required by this Section for the purpose of attribution + in the manner set out above and, by exercising Your rights under this + License, You may not implicitly or explicitly assert or imply any + connection with, sponsorship or endorsement by the Original Author, + Licensor and/or Attribution Parties, as appropriate, of You or Your + use of the Work, without the separate, express prior written + permission of the Original Author, Licensor and/or Attribution + Parties. + c. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION +OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of this License. + + Creative Commons may be contacted at http://creativecommons.org/.