<commit_before>package main

import (
	"fmt"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

type testCase struct {
	input    string
	expected string
}

func TestInterpolateLiteral(t *testing.T) {
	Convey("GIVEN: A test dictionary", t, func() {
		dict := newDictionary()
		for _, v := range []string{"", "literal", "foobarbaz$"} {
			Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", v), func() {
				actual, err := Interpolate(v, dict)
				Convey(fmt.Sprintf("THEN: Should be \"%s\"", v), func() {
					So(err, ShouldBeNil)
					So(actual, ShouldEqual, v)
				})
			})
			Convey(fmt.Sprintf("WHEN: Interpolating \"%s\" (strict mode)", v), func() {
				actual, err := StrictInterpolate(v, dict)
				Convey(fmt.Sprintf("THEN: Should be \"%s\"", v), func() {
					So(err, ShouldBeNil)
					So(actual, ShouldEqual, v)
				})
			})
		}
	})
}

func TestInterpolateExpansion(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("AND GIVEN: Test cases", func() {
			for _, v := range []testCase{
				{input: "${foo}", expected: "foo-value"},
				{input: "${baz}", expected: "baz-value, bar-value, foo-value"},
				{input: "${foo}$$${bar}", expected: "foo-value$bar-value, foo-value"}} {
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", v.input), func() {
					actual, err := Interpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\" (strict mode)", v.input), func() {
					actual, err := StrictInterpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
			}
		})
		Convey("WHEN Interpolating \"${mokeke}moke\"", func() {
			actual, err := Interpolate("${mokeke}moke", dict)
			Convey("THEN: Should be \"${mokeke}moke\"", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "moke")
			})
		})
		Convey("WHEN Interpolating \"${mokeke}moke\" (strict-mode)", func() {
			_, err := StrictInterpolate("${mokeke}moke", dict)
			Convey("THEN: Should cause an error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should be UnknownReference error", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnknownReference)
				})
			})
		})
	})
}

func TestInterpolateError(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("WHEN: Interpolte \"${foo\" (Unmatched {})", func() {
			_, err := Interpolate("${foo", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have UnmatchedBrace error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnmatchedBrace)
				})
			})
		})
		Convey("WHEN: Interpolate \"$foo\" (Passthrough unrecognized)", func() {
			actual, err := Interpolate("$foo", dict)
			Convey("THEN: Should success", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "$foo")
			})
		})
		Convey("WHEN: Interpolate \"${rec}\" (Exceeding recursion limit)", func() {
			actual, err := Interpolate("${rec}", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have ExceedRecursionLimit error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, ExceedRecursionLimit)
					Printf("actual: \"%s\"", actual)
				})
			})
		})
	})
}

func TestStrictInterpolateErrors(t *testing.T) {
	Convey("GIVEN: A new dictionary", t, func() {
		dict := newDictionary()
		type errTestCase struct {
			input string
			err   ErrorType
		}
		for _, tc := range []errTestCase{
			{"${foo", UnmatchedBrace},
			{"$foo", InvalidDollarSequence},
			{"${mokeke}moke", UnknownReference},
			{"${rec}", ExceedRecursionLimit}} {
			Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", tc.input), func() {
				actual, err := StrictInterpolate(tc.input, dict)
				Convey("THEN: Should cause an error", func() {
					So(err, ShouldNotBeNil)
					Convey(fmt.Sprintf("AND THEN: Should have %s error type", tc.err.String()), func() {
						e, ok := err.(*InterpolationError)
						So(ok, ShouldBeTrue)
						So(e.Type, ShouldEqual, tc.err)
						Printf("actual:\"%s\"\n", actual)
					})
				})
			})
		}
	})
}

func newDictionary() map[string]string {
	return map[string]string{
		"foo": "foo-value",
		"bar": "bar-value, ${foo}",
		"baz": "baz-value, ${bar}",
		"rec": "do${rec}"}
}
<commit_msg>test: Use property tests for literal interpolation<commit_after>package main

import (
	"fmt"
	"reflect"
	"strings"
	"testing"

	"github.com/leanovate/gopter"
	"github.com/leanovate/gopter/convey"
	"github.com/leanovate/gopter/gen"
	. "github.com/smartystreets/goconvey/convey"
)

type testCase struct {
	input    string
	expected string
}

func TestInterpolateLiteral(t *testing.T) {
	Convey("GIVEN: A empty dictionary", t, func() {
		dict := make(map[string]string)
		g := gen.AnyString().
			SuchThat(
				func(arg interface{}) bool {
					s := arg.(string)
					return !strings.ContainsAny(s, `${`)
				}).
			FlatMap(
				func(arg interface{}) gopter.Gen {
					s := arg.(string)
					return gen.OneConstOf(s, s+"$")
				},
				reflect.TypeOf(""))

		Convey(`WHEN: Apply property tests`, func() {
			condition := func(s string) bool {
				actual, err := Interpolate(s, dict)
				return err == nil && actual == s
			}
			Convey(`THEN: Should success for all`, func() {
				So(condition, convey.ShouldSucceedForAll, g)
			})
		})
		Convey(`WHEN: Apply property tests (strict)`, func() {
			condition := func(s string) bool {
				actual, err := StrictInterpolate(s, dict)

				return err == nil && actual == s
			}
			Convey(`THEN: Should success for all`, func() {
				So(condition, convey.ShouldSucceedForAll, g)
			})
		})
	})
}

func TestInterpolateExpansion(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("AND GIVEN: Test cases", func() {
			for _, v := range []testCase{
				{input: "${foo}", expected: "foo-value"},
				{input: "${baz}", expected: "baz-value, bar-value, foo-value"},
				{input: "${foo}$$${bar}", expected: "foo-value$bar-value, foo-value"}} {
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", v.input), func() {
					actual, err := Interpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\" (strict mode)", v.input), func() {
					actual, err := StrictInterpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
			}
		})
		Convey("WHEN Interpolating \"${mokeke}moke\"", func() {
			actual, err := Interpolate("${mokeke}moke", dict)
			Convey("THEN: Should be \"${mokeke}moke\"", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "moke")
			})
		})
		Convey("WHEN Interpolating \"${mokeke}moke\" (strict-mode)", func() {
			_, err := StrictInterpolate("${mokeke}moke", dict)
			Convey("THEN: Should cause an error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should be UnknownReference error", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnknownReference)
				})
			})
		})
	})
}

func TestInterpolateError(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("WHEN: Interpolte \"${foo\" (Unmatched {})", func() {
			_, err := Interpolate("${foo", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have UnmatchedBrace error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnmatchedBrace)
				})
			})
		})
		Convey("WHEN: Interpolate \"$foo\" (Passthrough unrecognized)", func() {
			actual, err := Interpolate("$foo", dict)
			Convey("THEN: Should success", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "$foo")
			})
		})
		Convey("WHEN: Interpolate \"${rec}\" (Exceeding recursion limit)", func() {
			actual, err := Interpolate("${rec}", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have ExceedRecursionLimit error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, ExceedRecursionLimit)
					Printf("actual: \"%s\"", actual)
				})
			})
		})
	})
}

func TestStrictInterpolateErrors(t *testing.T) {
	Convey("GIVEN: A new dictionary", t, func() {
		dict := newDictionary()
		type errTestCase struct {
			input string
			err   ErrorType
		}
		for _, tc := range []errTestCase{
			{"${foo", UnmatchedBrace},
			{"$foo", InvalidDollarSequence},
			{"${mokeke}moke", UnknownReference},
			{"${rec}", ExceedRecursionLimit}} {
			Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", tc.input), func() {
				actual, err := StrictInterpolate(tc.input, dict)
				Convey("THEN: Should cause an error", func() {
					So(err, ShouldNotBeNil)
					Convey(fmt.Sprintf("AND THEN: Should have %s error type", tc.err.String()), func() {
						e, ok := err.(*InterpolationError)
						So(ok, ShouldBeTrue)
						So(e.Type, ShouldEqual, tc.err)
						Printf("actual:\"%s\"\n", actual)
					})
				})
			})
		}
	})
}

func newDictionary() map[string]string {
	return map[string]string{
		"foo": "foo-value",
		"bar": "bar-value, ${foo}",
		"baz": "baz-value, ${bar}",
		"rec": "do${rec}"}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"reflect"
	"strings"
	"testing"

	"github.com/leanovate/gopter"
	"github.com/leanovate/gopter/convey"
	"github.com/leanovate/gopter/gen"
	. "github.com/smartystreets/goconvey/convey"
)

type testCase struct {
	input    string
	expected string
}

func TestInterpolateLiteral(t *testing.T) {
	Convey("GIVEN: A empty dictionary", t, func() {
		dict := make(map[string]string)
		g := gen.AnyString().
			SuchThat(
				func(arg interface{}) bool {
					s := arg.(string)
					return !strings.ContainsAny(s, `${`)
				}).
			FlatMap(
				func(arg interface{}) gopter.Gen {
					s := arg.(string)
					return gen.OneConstOf(s, s+"$")
				},
				reflect.TypeOf(""))

		Convey(`WHEN: Apply property tests`, func() {
			condition := func(s string) bool {
				actual, err := Interpolate(s, dict)
				return err == nil && actual == s
			}
			Convey(`THEN: Should success for all`, func() {
				So(condition, convey.ShouldSucceedForAll, g)
			})
		})
		Convey(`WHEN: Apply property tests (strict)`, func() {
			condition := func(s string) bool {
				actual, err := StrictInterpolate(s, dict)

				return err == nil && actual == s
			}
			Convey(`THEN: Should success for all`, func() {
				So(condition, convey.ShouldSucceedForAll, g)
			})
		})
	})
}

func TestInterpolateExpansion(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("AND GIVEN: Test cases", func() {
			for _, v := range []testCase{
				{input: "${foo}", expected: "foo-value"},
				{input: "${baz}", expected: "baz-value, bar-value, foo-value"},
				{input: "${foo}$$${bar}", expected: "foo-value$bar-value, foo-value"}} {
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", v.input), func() {
					actual, err := Interpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\" (strict mode)", v.input), func() {
					actual, err := StrictInterpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
			}
		})
		Convey("WHEN Interpolating \"${mokeke}moke\"", func() {
			actual, err := Interpolate("${mokeke}moke", dict)
			Convey("THEN: Should be \"${mokeke}moke\"", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "moke")
			})
		})
		Convey("WHEN Interpolating \"${mokeke}moke\" (strict-mode)", func() {
			_, err := StrictInterpolate("${mokeke}moke", dict)
			Convey("THEN: Should cause an error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should be UnknownReference error", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnknownReference)
				})
			})
		})
	})
}

func TestInterpolateError(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("WHEN: Interpolte \"${foo\" (Unmatched {})", func() {
			_, err := Interpolate("${foo", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have UnmatchedBrace error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnmatchedBrace)
				})
			})
		})
		Convey("WHEN: Interpolate \"$foo\" (Passthrough unrecognized)", func() {
			actual, err := Interpolate("$foo", dict)
			Convey("THEN: Should success", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "$foo")
			})
		})
		Convey("WHEN: Interpolate \"${rec}\" (Exceeding recursion limit)", func() {
			actual, err := Interpolate("${rec}", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have ExceedRecursionLimit error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, ExceedRecursionLimit)
					Printf("actual: \"%s\"", actual)
				})
			})
		})
	})
}

func TestStrictInterpolateErrors(t *testing.T) {
	Convey("GIVEN: A new dictionary", t, func() {
		dict := newDictionary()
		type errTestCase struct {
			input string
			err   ErrorType
		}
		for _, tc := range []errTestCase{
			{"${foo", UnmatchedBrace},
			{"$foo", InvalidDollarSequence},
			{"${mokeke}moke", UnknownReference},
			{"${rec}", ExceedRecursionLimit}} {
			Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", tc.input), func() {
				actual, err := StrictInterpolate(tc.input, dict)
				Convey("THEN: Should cause an error", func() {
					So(err, ShouldNotBeNil)
					Convey(fmt.Sprintf("AND THEN: Should have %s error type", tc.err.String()), func() {
						e, ok := err.(*InterpolationError)
						So(ok, ShouldBeTrue)
						So(e.Type, ShouldEqual, tc.err)
						Printf("actual:\"%s\"\n", actual)
					})
				})
			})
		}
	})
}

func newDictionary() map[string]string {
	return map[string]string{
		"foo": "foo-value",
		"bar": "bar-value, ${foo}",
		"baz": "baz-value, ${bar}",
		"rec": "do${rec}"}
}
<commit_msg>chore: Remove `Printf`<commit_after>package main

import (
	"fmt"
	"reflect"
	"strings"
	"testing"

	"github.com/leanovate/gopter"
	"github.com/leanovate/gopter/convey"
	"github.com/leanovate/gopter/gen"
	. "github.com/smartystreets/goconvey/convey"
)

type testCase struct {
	input    string
	expected string
}

func TestInterpolateLiteral(t *testing.T) {
	Convey("GIVEN: A empty dictionary", t, func() {
		dict := make(map[string]string)
		g := gen.AnyString().
			SuchThat(
				func(arg interface{}) bool {
					s := arg.(string)
					return !strings.ContainsAny(s, `${`)
				}).
			FlatMap(
				func(arg interface{}) gopter.Gen {
					s := arg.(string)
					return gen.OneConstOf(s, s+"$")
				},
				reflect.TypeOf(""))

		Convey(`WHEN: Apply property tests`, func() {
			condition := func(s string) bool {
				actual, err := Interpolate(s, dict)
				return err == nil && actual == s
			}
			Convey(`THEN: Should success for all`, func() {
				So(condition, convey.ShouldSucceedForAll, g)
			})
		})
		Convey(`WHEN: Apply property tests (strict)`, func() {
			condition := func(s string) bool {
				actual, err := StrictInterpolate(s, dict)

				return err == nil && actual == s
			}
			Convey(`THEN: Should success for all`, func() {
				So(condition, convey.ShouldSucceedForAll, g)
			})
		})
	})
}

func TestInterpolateExpansion(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("AND GIVEN: Test cases", func() {
			for _, v := range []testCase{
				{input: "${foo}", expected: "foo-value"},
				{input: "${baz}", expected: "baz-value, bar-value, foo-value"},
				{input: "${foo}$$${bar}", expected: "foo-value$bar-value, foo-value"}} {
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", v.input), func() {
					actual, err := Interpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
				Convey(fmt.Sprintf("WHEN: Interpolating \"%s\" (strict mode)", v.input), func() {
					actual, err := StrictInterpolate(v.input, dict)
					Convey(fmt.Sprintf("THEN: Should be \"%s\"", v.expected), func() {
						So(err, ShouldBeNil)
						So(actual, ShouldEqual, v.expected)
					})
				})
			}
		})
		Convey("WHEN Interpolating \"${mokeke}moke\"", func() {
			actual, err := Interpolate("${mokeke}moke", dict)
			Convey("THEN: Should be \"${mokeke}moke\"", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "moke")
			})
		})
		Convey("WHEN Interpolating \"${mokeke}moke\" (strict-mode)", func() {
			_, err := StrictInterpolate("${mokeke}moke", dict)
			Convey("THEN: Should cause an error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should be UnknownReference error", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnknownReference)
				})
			})
		})
	})
}

func TestInterpolateError(t *testing.T) {
	Convey("GIVEN: A Test dictionary", t, func() {
		dict := newDictionary()
		Convey("WHEN: Interpolte \"${foo\" (Unmatched {})", func() {
			_, err := Interpolate("${foo", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have UnmatchedBrace error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, UnmatchedBrace)
				})
			})
		})
		Convey("WHEN: Interpolate \"$foo\" (Passthrough unrecognized)", func() {
			actual, err := Interpolate("$foo", dict)
			Convey("THEN: Should success", func() {
				So(err, ShouldBeNil)
				So(actual, ShouldEqual, "$foo")
			})
		})
		Convey("WHEN: Interpolate \"${rec}\" (Exceeding recursion limit)", func() {
			actual, err := Interpolate("${rec}", dict)
			Convey("THEN: Should cause error", func() {
				So(err, ShouldNotBeNil)
				Convey("AND THEN: Should have ExceedRecursionLimit error type", func() {
					e, ok := err.(*InterpolationError)
					So(ok, ShouldBeTrue)
					So(e.Type, ShouldEqual, ExceedRecursionLimit)
					Printf("actual: \"%s\"", actual)
				})
			})
		})
	})
}

func TestStrictInterpolateErrors(t *testing.T) {
	Convey("GIVEN: A new dictionary", t, func() {
		dict := newDictionary()
		type errTestCase struct {
			input string
			err   ErrorType
		}
		for _, tc := range []errTestCase{
			{"${foo", UnmatchedBrace},
			{"$foo", InvalidDollarSequence},
			{"${mokeke}moke", UnknownReference},
			{"${rec}", ExceedRecursionLimit}} {
			Convey(fmt.Sprintf("WHEN: Interpolating \"%s\"", tc.input), func() {
				_, err := StrictInterpolate(tc.input, dict)
				Convey("THEN: Should cause an error", func() {
					So(err, ShouldNotBeNil)
					Convey(fmt.Sprintf("AND THEN: Should have %s error type", tc.err.String()), func() {
						e, ok := err.(*InterpolationError)
						So(ok, ShouldBeTrue)
						So(e.Type, ShouldEqual, tc.err)
					})
				})
			})
		}
	})
}

func newDictionary() map[string]string {
	return map[string]string{
		"foo": "foo-value",
		"bar": "bar-value, ${foo}",
		"baz": "baz-value, ${bar}",
		"rec": "do${rec}"}
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"database/sql"
	"flag"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/peterh/liner"
	"github.com/pingcap/tidb"
	"github.com/pingcap/tidb/util/errors2"
	"github.com/pingcap/tidb/util/printer"
)

var (
	logLevel = flag.String("L", "error", "log level")
	store    = flag.String("store", "goleveldb", "the name for the registered storage, e.g. memory, goleveldb, boltdb")
	dbPath   = flag.String("dbpath", "test", "db path")

	line        *liner.State
	historyPath = "/tmp/tidb_interpreter"
)

func openHistory() {
	if f, err := os.Open(historyPath); err == nil {
		line.ReadHistory(f)
		f.Close()
	}
}

func saveHistory() {
	if f, err := os.Create(historyPath); err == nil {
		line.WriteHistory(f)
		f.Close()
	}
}

func executeLine(tx *sql.Tx, txnLine string) error {
	if tidb.IsQuery(txnLine) {
		rows, err := tx.Query(txnLine)
		if err != nil {
			return errors.Trace(err)
		}
		defer rows.Close()
		cols, err := rows.Columns()
		if err != nil {
			return errors.Trace(err)
		}

		values := make([][]byte, len(cols))
		scanArgs := make([]interface{}, len(values))
		for i := range values {
			scanArgs[i] = &values[i]
		}

		var datas [][]string
		for rows.Next() {
			err := rows.Scan(scanArgs...)
			if err != nil {
				return errors.Trace(err)
			}

			data := make([]string, len(cols))
			for i, value := range values {
				if value == nil {
					data[i] = "NULL"
				} else {
					data[i] = string(value)
				}
			}

			datas = append(datas, data)
		}

		// For `cols` and `datas[i]` always has the same length,
		// no need to check return validity.
		result, _ := printer.GetPrintResult(cols, datas)
		fmt.Printf("%s", result)

		if err := rows.Err(); err != nil {
			return errors.Trace(err)
		}
	} else {
		// TODO: rows affected and last insert id
		_, err := tx.Exec(txnLine)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

func mayExit(err error, l string) bool {
	if errors2.ErrorEqual(err, liner.ErrPromptAborted) || errors2.ErrorEqual(err, io.EOF) {
		fmt.Println("\nBye")
		saveHistory()
		line.Close()
		return true
	}
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}
	return false
}

func readStatement(prompt string) (string, error) {
	var ret string
	for {
		l, err := line.Prompt(prompt)
		if err != nil {
			return "", err
		}
		if strings.HasSuffix(l, ";") == false {
			ret += l + "\n"
			prompt = "   -> "
			continue
		}
		return ret + l, nil
	}
}

func main() {
	printer.PrintTiDBInfo()

	flag.Parse()
	log.SetLevelByString(*logLevel)
	// support for signal notify
	runtime.GOMAXPROCS(runtime.NumCPU())

	line = liner.NewLiner()
	defer line.Close()

	line.SetCtrlCAborts(true)
	openHistory()

	mdb, err := sql.Open(tidb.DriverName, *store+"://"+*dbPath)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}

	for {
		l, err := readStatement("tidb> ")
		if mayExit(err, l) {
			return
		}
		line.AppendHistory(l)

		// if we're in transaction
		if strings.HasPrefix(l, "BEGIN") || strings.HasPrefix(l, "begin") {
			tx, err := mdb.Begin()
			if err != nil {
				log.Error(errors.ErrorStack(err))
				continue
			}
			for {
				txnLine, err := readStatement(">> ")
				if mayExit(err, txnLine) {
					return
				}
				line.AppendHistory(txnLine)

				if !strings.HasSuffix(txnLine, ";") {
					txnLine += ";"
				}

				if strings.HasPrefix(txnLine, "COMMIT") || strings.HasPrefix(txnLine, "commit") {
					err := tx.Commit()
					if err != nil {
						log.Error(errors.ErrorStack(err))
						tx.Rollback()
					}
					break
				}
				// normal sql statement
				err = executeLine(tx, txnLine)
				if err != nil {
					log.Error(errors.ErrorStack(err))
					tx.Rollback()
					break
				}
			}
		} else {
			tx, err := mdb.Begin()
			if err != nil {
				log.Error(errors.ErrorStack(err))
				continue
			}
			err = executeLine(tx, l)
			if err != nil {
				log.Error(errors.ErrorStack(err))
				tx.Rollback()
			} else {
				tx.Commit()
			}
		}
	}
}
<commit_msg>interpreter: remove redundant Close.<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"database/sql"
	"flag"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/peterh/liner"
	"github.com/pingcap/tidb"
	"github.com/pingcap/tidb/util/errors2"
	"github.com/pingcap/tidb/util/printer"
)

var (
	logLevel = flag.String("L", "error", "log level")
	store    = flag.String("store", "goleveldb", "the name for the registered storage, e.g. memory, goleveldb, boltdb")
	dbPath   = flag.String("dbpath", "test", "db path")

	line        *liner.State
	historyPath = "/tmp/tidb_interpreter"
)

func openHistory() {
	if f, err := os.Open(historyPath); err == nil {
		line.ReadHistory(f)
		f.Close()
	}
}

func saveHistory() {
	if f, err := os.Create(historyPath); err == nil {
		line.WriteHistory(f)
		f.Close()
	}
}

func executeLine(tx *sql.Tx, txnLine string) error {
	if tidb.IsQuery(txnLine) {
		rows, err := tx.Query(txnLine)
		if err != nil {
			return errors.Trace(err)
		}
		defer rows.Close()
		cols, err := rows.Columns()
		if err != nil {
			return errors.Trace(err)
		}

		values := make([][]byte, len(cols))
		scanArgs := make([]interface{}, len(values))
		for i := range values {
			scanArgs[i] = &values[i]
		}

		var datas [][]string
		for rows.Next() {
			err := rows.Scan(scanArgs...)
			if err != nil {
				return errors.Trace(err)
			}

			data := make([]string, len(cols))
			for i, value := range values {
				if value == nil {
					data[i] = "NULL"
				} else {
					data[i] = string(value)
				}
			}

			datas = append(datas, data)
		}

		// For `cols` and `datas[i]` always has the same length,
		// no need to check return validity.
		result, _ := printer.GetPrintResult(cols, datas)
		fmt.Printf("%s", result)

		if err := rows.Err(); err != nil {
			return errors.Trace(err)
		}
	} else {
		// TODO: rows affected and last insert id
		_, err := tx.Exec(txnLine)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

func mayExit(err error, l string) bool {
	if errors2.ErrorEqual(err, liner.ErrPromptAborted) || errors2.ErrorEqual(err, io.EOF) {
		fmt.Println("\nBye")
		saveHistory()
		return true
	}
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}
	return false
}

func readStatement(prompt string) (string, error) {
	var ret string
	for {
		l, err := line.Prompt(prompt)
		if err != nil {
			return "", err
		}
		if strings.HasSuffix(l, ";") == false {
			ret += l + "\n"
			prompt = "   -> "
			continue
		}
		return ret + l, nil
	}
}

func main() {
	printer.PrintTiDBInfo()

	flag.Parse()
	log.SetLevelByString(*logLevel)
	// support for signal notify
	runtime.GOMAXPROCS(runtime.NumCPU())

	line = liner.NewLiner()
	defer line.Close()

	line.SetCtrlCAborts(true)
	openHistory()

	mdb, err := sql.Open(tidb.DriverName, *store+"://"+*dbPath)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}

	for {
		l, err := readStatement("tidb> ")
		if mayExit(err, l) {
			return
		}
		line.AppendHistory(l)

		// if we're in transaction
		if strings.HasPrefix(l, "BEGIN") || strings.HasPrefix(l, "begin") {
			tx, err := mdb.Begin()
			if err != nil {
				log.Error(errors.ErrorStack(err))
				continue
			}
			for {
				txnLine, err := readStatement(">> ")
				if mayExit(err, txnLine) {
					return
				}
				line.AppendHistory(txnLine)

				if !strings.HasSuffix(txnLine, ";") {
					txnLine += ";"
				}

				if strings.HasPrefix(txnLine, "COMMIT") || strings.HasPrefix(txnLine, "commit") {
					err := tx.Commit()
					if err != nil {
						log.Error(errors.ErrorStack(err))
						tx.Rollback()
					}
					break
				}
				// normal sql statement
				err = executeLine(tx, txnLine)
				if err != nil {
					log.Error(errors.ErrorStack(err))
					tx.Rollback()
					break
				}
			}
		} else {
			tx, err := mdb.Begin()
			if err != nil {
				log.Error(errors.ErrorStack(err))
				continue
			}
			err = executeLine(tx, l)
			if err != nil {
				log.Error(errors.ErrorStack(err))
				tx.Rollback()
			} else {
				tx.Commit()
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 by Richard A. Wilkes. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, version 2.0.

package ui

import (
	"github.com/richardwilkes/geom"
	"github.com/richardwilkes/ui/color"
	"github.com/richardwilkes/ui/draw"
	"github.com/richardwilkes/ui/event"
	"github.com/richardwilkes/ui/keys"
	"github.com/richardwilkes/ui/theme"
	"math"
	"time"
)

// Possible values for CheckBoxState.
const (
	Unchecked CheckBoxState = iota
	Mixed
	Checked
)

// CheckBoxState represents the current state of the checkbox.
type CheckBoxState int

// CheckBox represents a clickable checkbox with an optional label.
type CheckBox struct {
	Block
	Theme   *theme.CheckBox // The theme the checkbox will use to draw itself.
	Title   string          // An optional title for the checkbox.
	state   CheckBoxState
	pressed bool
}

// NewCheckBox creates a new checkbox with the specified title.
func NewCheckBox(title string) *CheckBox {
	checkbox := &CheckBox{}
	checkbox.Title = title
	checkbox.Theme = theme.StdCheckBox
	checkbox.SetFocusable(true)
	checkbox.SetSizer(checkbox)
	handlers := checkbox.EventHandlers()
	handlers.Add(event.PaintType, checkbox.paint)
	handlers.Add(event.MouseDownType, checkbox.mouseDown)
	handlers.Add(event.MouseDraggedType, checkbox.mouseDragged)
	handlers.Add(event.MouseUpType, checkbox.mouseUp)
	handlers.Add(event.FocusGainedType, checkbox.focusChanged)
	handlers.Add(event.FocusLostType, checkbox.focusChanged)
	handlers.Add(event.KeyDownType, checkbox.keyDown)
	return checkbox
}

func (checkbox *CheckBox) BoxSize() float64 {
	return math.Ceil(checkbox.Theme.Font.Ascent() + checkbox.Theme.Font.Descent())
}

// Sizes implements Sizer
func (checkbox *CheckBox) Sizes(hint geom.Size) (min, pref, max geom.Size) {
	var size geom.Size
	box := checkbox.BoxSize()
	if checkbox.Title != "" {
		if hint.Width != NoHint {
			hint.Width -= checkbox.Theme.HorizontalGap + box
			if hint.Width < 1 {
				hint.Width = 1
			}
		}
		if hint.Height != NoHint {
			if hint.Height < 1 {
				hint.Height = 1
			}
		}
		size = checkbox.Theme.Font.Measure(checkbox.Title)
		size.GrowToInteger()
		size.ConstrainForHint(hint)
		size.Width += checkbox.Theme.HorizontalGap + box
		if size.Height < box {
			size.Height = box
		}
	} else {
		size.Width = box
		size.Height = box
	}
	if border := checkbox.Border(); border != nil {
		size.AddInsets(border.Insets())
	}
	return size, size, DefaultMaxSize(size)
}

func (checkbox *CheckBox) paint(evt event.Event) {
	box := checkbox.BoxSize()
	bounds := checkbox.LocalInsetBounds()
	bounds.Width = box
	bounds.Y += (bounds.Height - box) / 2
	bounds.Height = box
	path := draw.NewPath()
	path.MoveTo(bounds.X, bounds.Y+checkbox.Theme.CornerRadius)
	path.QuadCurveTo(bounds.X, bounds.Y, bounds.X+checkbox.Theme.CornerRadius, bounds.Y)
	path.LineTo(bounds.X+bounds.Width-checkbox.Theme.CornerRadius, bounds.Y)
	path.QuadCurveTo(bounds.X+bounds.Width, bounds.Y, bounds.X+bounds.Width, bounds.Y+checkbox.Theme.CornerRadius)
	path.LineTo(bounds.X+bounds.Width, bounds.Y+bounds.Height-checkbox.Theme.CornerRadius)
	path.QuadCurveTo(bounds.X+bounds.Width, bounds.Y+bounds.Height, bounds.X+bounds.Width-checkbox.Theme.CornerRadius, bounds.Y+bounds.Height)
	path.LineTo(bounds.X+checkbox.Theme.CornerRadius, bounds.Y+bounds.Height)
	path.QuadCurveTo(bounds.X, bounds.Y+bounds.Height, bounds.X, bounds.Y+bounds.Height-checkbox.Theme.CornerRadius)
	path.ClosePath()
	gc := evt.(*event.Paint).GC()
	gc.AddPath(path)
	gc.Save()
	gc.Clip()
	base := checkbox.BaseBackground()
	gc.AddPath(path)
	if checkbox.Enabled() {
		paint := draw.NewLinearGradientPaint(checkbox.Theme.Gradient(base), bounds.X+bounds.Width/2, bounds.Y+1, bounds.X+bounds.Width/2, bounds.Y+bounds.Height-1)
		gc.SetPaint(paint)
		gc.FillPath()
		paint.Dispose()
	} else {
		gc.SetColor(color.Background)
		gc.FillPath()
	}
	gc.AddPath(path)
	gc.SetColor(base.AdjustBrightness(checkbox.Theme.OutlineAdjustment))
	gc.StrokePath()
	gc.Restore()
	switch checkbox.state {
	case Mixed:
		gc.Save()
		gc.SetColor(checkbox.stateColor(base))
		gc.SetStrokeWidth(2)
		gc.StrokeLine(bounds.X+bounds.Width*0.25, bounds.Y+bounds.Height*0.5, bounds.X+bounds.Width*0.7, bounds.Y+bounds.Height*0.5)
		gc.Restore()
	case Checked:
		gc.Save()
		gc.SetColor(checkbox.stateColor(base))
		gc.SetStrokeWidth(2)
		gc.BeginPath()
		gc.MoveTo(bounds.X+bounds.Width*0.25, bounds.Y+bounds.Height*0.55)
		gc.LineTo(bounds.X+bounds.Width*0.45, bounds.Y+bounds.Height*0.7)
		gc.LineTo(bounds.X+bounds.Width*0.75, bounds.Y+bounds.Height*0.3)
		gc.StrokePath()
		gc.Restore()
	}
	if checkbox.Title != "" {
		bounds = checkbox.LocalInsetBounds()
		if bounds.Width-(box+checkbox.Theme.HorizontalGap) > 0 {
			gc.SetColor(checkbox.TextColor())
			gc.DrawString(bounds.X+box+checkbox.Theme.HorizontalGap, bounds.Y, checkbox.Title, checkbox.Theme.Font)
		}
	}
}

func (checkbox *CheckBox) mouseDown(evt event.Event) {
	checkbox.pressed = true
	checkbox.Repaint()
}

func (checkbox *CheckBox) mouseDragged(evt event.Event) {
	bounds := checkbox.LocalInsetBounds()
	pressed := bounds.Contains(checkbox.FromWindow(evt.(*event.MouseDragged).Where()))
	if checkbox.pressed != pressed {
		checkbox.pressed = pressed
		checkbox.Repaint()
	}
}

func (checkbox *CheckBox) mouseUp(evt event.Event) {
	checkbox.pressed = false
	checkbox.Repaint()
	bounds := checkbox.LocalInsetBounds()
	if bounds.Contains(checkbox.FromWindow(evt.(*event.MouseUp).Where())) {
		checkbox.Click()
	}
}

// Click performs any animation associated with a click and calls the OnClick() function if it is
// set.
func (checkbox *CheckBox) Click() {
	if checkbox.state == Checked {
		checkbox.state = Unchecked
	} else {
		checkbox.state = Checked
	}
	pressed := checkbox.pressed
	checkbox.pressed = true
	checkbox.Repaint()
	checkbox.Window().FlushPainting()
	checkbox.pressed = pressed
	time.Sleep(checkbox.Theme.ClickAnimationTime)
	checkbox.Repaint()
	event.Dispatch(event.NewClick(checkbox))
}

func (checkbox *CheckBox) focusChanged(evt event.Event) {
	checkbox.Repaint()
}

func (checkbox *CheckBox) keyDown(evt event.Event) {
	if keys.IsControlAction(evt.(*event.KeyDown).Code()) {
		evt.Finish()
		checkbox.Click()
	}
}

func (checkbox *CheckBox) stateColor(base color.Color) color.Color {
	if !checkbox.Enabled() {
		return checkbox.Theme.TextWhenDisabled
	}
	if checkbox.BaseBackground().Luminance() > 0.65 {
		return checkbox.Theme.TextWhenLight
	}
	return checkbox.Theme.TextWhenDark
}

// BaseBackground returns this checkbox's current base background color.
func (checkbox *CheckBox) BaseBackground() color.Color {
	switch {
	case !checkbox.Enabled():
		return checkbox.Theme.Background.AdjustBrightness(checkbox.Theme.DisabledAdjustment)
	case checkbox.pressed:
		return checkbox.Theme.BackgroundWhenPressed
	case checkbox.Focused():
		return checkbox.Theme.Background.Blend(color.KeyboardFocus, 0.5)
	default:
		return checkbox.Theme.Background
	}
}

// TextColor returns this checkbox's current text color.
func (checkbox *CheckBox) TextColor() color.Color {
	if !checkbox.Enabled() {
		return checkbox.Theme.TextWhenDisabled
	}
	return checkbox.Theme.TextWhenLight
}

// State returns this checkbox's current state.
func (checkbox *CheckBox) State() CheckBoxState {
	return checkbox.state
}

// SetState sets the checkbox's state.
func (checkbox *CheckBox) SetState(state CheckBoxState) {
	if checkbox.state != state {
		checkbox.state = state
		checkbox.Repaint()
	}
}
<commit_msg>Don't export BoxSize<commit_after>// Copyright (c) 2016 by Richard A. Wilkes. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, version 2.0.

package ui

import (
	"github.com/richardwilkes/geom"
	"github.com/richardwilkes/ui/color"
	"github.com/richardwilkes/ui/draw"
	"github.com/richardwilkes/ui/event"
	"github.com/richardwilkes/ui/keys"
	"github.com/richardwilkes/ui/theme"
	"math"
	"time"
)

// Possible values for CheckBoxState.
const (
	Unchecked CheckBoxState = iota
	Mixed
	Checked
)

// CheckBoxState represents the current state of the checkbox.
type CheckBoxState int

// CheckBox represents a clickable checkbox with an optional label.
type CheckBox struct {
	Block
	Theme   *theme.CheckBox // The theme the checkbox will use to draw itself.
	Title   string          // An optional title for the checkbox.
	state   CheckBoxState
	pressed bool
}

// NewCheckBox creates a new checkbox with the specified title.
func NewCheckBox(title string) *CheckBox {
	checkbox := &CheckBox{}
	checkbox.Title = title
	checkbox.Theme = theme.StdCheckBox
	checkbox.SetFocusable(true)
	checkbox.SetSizer(checkbox)
	handlers := checkbox.EventHandlers()
	handlers.Add(event.PaintType, checkbox.paint)
	handlers.Add(event.MouseDownType, checkbox.mouseDown)
	handlers.Add(event.MouseDraggedType, checkbox.mouseDragged)
	handlers.Add(event.MouseUpType, checkbox.mouseUp)
	handlers.Add(event.FocusGainedType, checkbox.focusChanged)
	handlers.Add(event.FocusLostType, checkbox.focusChanged)
	handlers.Add(event.KeyDownType, checkbox.keyDown)
	return checkbox
}

func (checkbox *CheckBox) boxSize() float64 {
	return math.Ceil(checkbox.Theme.Font.Ascent() + checkbox.Theme.Font.Descent())
}

// Sizes implements Sizer
func (checkbox *CheckBox) Sizes(hint geom.Size) (min, pref, max geom.Size) {
	var size geom.Size
	box := checkbox.boxSize()
	if checkbox.Title != "" {
		if hint.Width != NoHint {
			hint.Width -= checkbox.Theme.HorizontalGap + box
			if hint.Width < 1 {
				hint.Width = 1
			}
		}
		if hint.Height != NoHint {
			if hint.Height < 1 {
				hint.Height = 1
			}
		}
		size = checkbox.Theme.Font.Measure(checkbox.Title)
		size.GrowToInteger()
		size.ConstrainForHint(hint)
		size.Width += checkbox.Theme.HorizontalGap + box
		if size.Height < box {
			size.Height = box
		}
	} else {
		size.Width = box
		size.Height = box
	}
	if border := checkbox.Border(); border != nil {
		size.AddInsets(border.Insets())
	}
	return size, size, DefaultMaxSize(size)
}

func (checkbox *CheckBox) paint(evt event.Event) {
	box := checkbox.boxSize()
	bounds := checkbox.LocalInsetBounds()
	bounds.Width = box
	bounds.Y += (bounds.Height - box) / 2
	bounds.Height = box
	path := draw.NewPath()
	path.MoveTo(bounds.X, bounds.Y+checkbox.Theme.CornerRadius)
	path.QuadCurveTo(bounds.X, bounds.Y, bounds.X+checkbox.Theme.CornerRadius, bounds.Y)
	path.LineTo(bounds.X+bounds.Width-checkbox.Theme.CornerRadius, bounds.Y)
	path.QuadCurveTo(bounds.X+bounds.Width, bounds.Y, bounds.X+bounds.Width, bounds.Y+checkbox.Theme.CornerRadius)
	path.LineTo(bounds.X+bounds.Width, bounds.Y+bounds.Height-checkbox.Theme.CornerRadius)
	path.QuadCurveTo(bounds.X+bounds.Width, bounds.Y+bounds.Height, bounds.X+bounds.Width-checkbox.Theme.CornerRadius, bounds.Y+bounds.Height)
	path.LineTo(bounds.X+checkbox.Theme.CornerRadius, bounds.Y+bounds.Height)
	path.QuadCurveTo(bounds.X, bounds.Y+bounds.Height, bounds.X, bounds.Y+bounds.Height-checkbox.Theme.CornerRadius)
	path.ClosePath()
	gc := evt.(*event.Paint).GC()
	gc.AddPath(path)
	gc.Save()
	gc.Clip()
	base := checkbox.BaseBackground()
	gc.AddPath(path)
	if checkbox.Enabled() {
		paint := draw.NewLinearGradientPaint(checkbox.Theme.Gradient(base), bounds.X+bounds.Width/2, bounds.Y+1, bounds.X+bounds.Width/2, bounds.Y+bounds.Height-1)
		gc.SetPaint(paint)
		gc.FillPath()
		paint.Dispose()
	} else {
		gc.SetColor(color.Background)
		gc.FillPath()
	}
	gc.AddPath(path)
	gc.SetColor(base.AdjustBrightness(checkbox.Theme.OutlineAdjustment))
	gc.StrokePath()
	gc.Restore()
	switch checkbox.state {
	case Mixed:
		gc.Save()
		gc.SetColor(checkbox.stateColor(base))
		gc.SetStrokeWidth(2)
		gc.StrokeLine(bounds.X+bounds.Width*0.25, bounds.Y+bounds.Height*0.5, bounds.X+bounds.Width*0.7, bounds.Y+bounds.Height*0.5)
		gc.Restore()
	case Checked:
		gc.Save()
		gc.SetColor(checkbox.stateColor(base))
		gc.SetStrokeWidth(2)
		gc.BeginPath()
		gc.MoveTo(bounds.X+bounds.Width*0.25, bounds.Y+bounds.Height*0.55)
		gc.LineTo(bounds.X+bounds.Width*0.45, bounds.Y+bounds.Height*0.7)
		gc.LineTo(bounds.X+bounds.Width*0.75, bounds.Y+bounds.Height*0.3)
		gc.StrokePath()
		gc.Restore()
	}
	if checkbox.Title != "" {
		bounds = checkbox.LocalInsetBounds()
		if bounds.Width-(box+checkbox.Theme.HorizontalGap) > 0 {
			gc.SetColor(checkbox.TextColor())
			gc.DrawString(bounds.X+box+checkbox.Theme.HorizontalGap, bounds.Y, checkbox.Title, checkbox.Theme.Font)
		}
	}
}

func (checkbox *CheckBox) mouseDown(evt event.Event) {
	checkbox.pressed = true
	checkbox.Repaint()
}

func (checkbox *CheckBox) mouseDragged(evt event.Event) {
	bounds := checkbox.LocalInsetBounds()
	pressed := bounds.Contains(checkbox.FromWindow(evt.(*event.MouseDragged).Where()))
	if checkbox.pressed != pressed {
		checkbox.pressed = pressed
		checkbox.Repaint()
	}
}

func (checkbox *CheckBox) mouseUp(evt event.Event) {
	checkbox.pressed = false
	checkbox.Repaint()
	bounds := checkbox.LocalInsetBounds()
	if bounds.Contains(checkbox.FromWindow(evt.(*event.MouseUp).Where())) {
		checkbox.Click()
	}
}

// Click performs any animation associated with a click and calls the OnClick() function if it is
// set.
func (checkbox *CheckBox) Click() {
	if checkbox.state == Checked {
		checkbox.state = Unchecked
	} else {
		checkbox.state = Checked
	}
	pressed := checkbox.pressed
	checkbox.pressed = true
	checkbox.Repaint()
	checkbox.Window().FlushPainting()
	checkbox.pressed = pressed
	time.Sleep(checkbox.Theme.ClickAnimationTime)
	checkbox.Repaint()
	event.Dispatch(event.NewClick(checkbox))
}

func (checkbox *CheckBox) focusChanged(evt event.Event) {
	checkbox.Repaint()
}

func (checkbox *CheckBox) keyDown(evt event.Event) {
	if keys.IsControlAction(evt.(*event.KeyDown).Code()) {
		evt.Finish()
		checkbox.Click()
	}
}

func (checkbox *CheckBox) stateColor(base color.Color) color.Color {
	if !checkbox.Enabled() {
		return checkbox.Theme.TextWhenDisabled
	}
	if checkbox.BaseBackground().Luminance() > 0.65 {
		return checkbox.Theme.TextWhenLight
	}
	return checkbox.Theme.TextWhenDark
}

// BaseBackground returns this checkbox's current base background color.
func (checkbox *CheckBox) BaseBackground() color.Color {
	switch {
	case !checkbox.Enabled():
		return checkbox.Theme.Background.AdjustBrightness(checkbox.Theme.DisabledAdjustment)
	case checkbox.pressed:
		return checkbox.Theme.BackgroundWhenPressed
	case checkbox.Focused():
		return checkbox.Theme.Background.Blend(color.KeyboardFocus, 0.5)
	default:
		return checkbox.Theme.Background
	}
}

// TextColor returns this checkbox's current text color.
func (checkbox *CheckBox) TextColor() color.Color {
	if !checkbox.Enabled() {
		return checkbox.Theme.TextWhenDisabled
	}
	return checkbox.Theme.TextWhenLight
}

// State returns this checkbox's current state.
func (checkbox *CheckBox) State() CheckBoxState {
	return checkbox.state
}

// SetState sets the checkbox's state.
func (checkbox *CheckBox) SetState(state CheckBoxState) {
	if checkbox.state != state {
		checkbox.state = state
		checkbox.Repaint()
	}
}
<|endoftext|>


<commit_before>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0755); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0755); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, 0755); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, 0755); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, 0755); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTree(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTree(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTree(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>ンンー ンンンン ンーンン<commit_after>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

//
// Setup permissions for the given directories used here.
//
const (
	tempDirPerms       = 0755
	localMediaDirPerms = 0755
	localLogDirPerms   = 0755
)

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, localMediaDirPerms); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, localMediaDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, localLogDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTree(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTree(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTree(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const (
	Version            = "0.5.3"
	tempDirPerms       = 0755
	localMediaDirPerms = 0755
	localLogDirPerms   = 0755
)

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	GitCommit          string
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string // parent of index / config / hooks etc
	LocalGitStorageDir string // parent of objects/lfs (may be same as LocalGitDir but may not)
	LocalMediaDir      string // root of lfs objects
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func localMediaDirNoCreate(sha string) string {
	return filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
}
func localMediaPathNoCreate(sha string) string {
	return filepath.Join(localMediaDirNoCreate(sha), sha)
}

func LocalMediaPath(sha string) (string, error) {
	path := localMediaDirNoCreate(sha)
	if err := os.MkdirAll(path, localMediaDirPerms); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func ObjectExistsOfSize(sha string, size int64) bool {
	path := localMediaPathNoCreate(sha)
	return FileExistsOfSize(path, size)
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 0, len(osEnviron)+7)
	env = append(env,
		fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir),
		fmt.Sprintf("LocalGitDir=%s", LocalGitDir),
		fmt.Sprintf("LocalGitStorageDir=%s", LocalGitStorageDir),
		fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir),
		fmt.Sprintf("TempDir=%s", TempDir),
		fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers()),
		fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer()),
	)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalGitStorageDir = resolveGitStorageDir(LocalGitDir)
		LocalMediaDir = filepath.Join(LocalGitStorageDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp") // temp files per worktree

		if err := os.MkdirAll(LocalMediaDir, localMediaDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, localLogDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	gitCommit := ""
	if len(GitCommit) > 0 {
		gitCommit = "; git " + GitCommit
	}
	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s%s)",
		Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1),
		gitCommit,
	)
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTreeVar(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTreeVar(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTreeVar(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	return processGitRedirectFile(file, gitPtrPrefix)
}

func processGitRedirectFile(file, prefix string) (string, error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return "", err
	}

	contents := string(data)
	var dir string
	if len(prefix) > 0 {
		if !strings.HasPrefix(contents, prefix) {
			// Prefix required & not found
			return "", nil
		}
		dir = strings.TrimSpace(contents[len(prefix):])
	} else {
		dir = strings.TrimSpace(contents)
	}

	if !filepath.IsAbs(dir) {
		// The .git file contains a relative path.
		// Create an absolute path based on the directory the .git file is located in.
		dir = filepath.Join(filepath.Dir(file), dir)
	}

	return dir, nil
}

// From a git dir, get the location that objects are to be stored (we will store lfs alongside)
// Sometimes there is an additional level of redirect on the .git folder by way of a commondir file
// before you find object storage, e.g. 'git worktree' uses this. It redirects to gitdir either by GIT_DIR
// (during setup) or .git/git-dir: (during use), but this only contains the index etc, the objects
// are found in another git dir via 'commondir'.
func resolveGitStorageDir(gitDir string) string {
	commondirpath := filepath.Join(gitDir, "commondir")
	if FileExists(commondirpath) && !DirExists(filepath.Join(gitDir, "objects")) {
		// no git-dir: prefix in commondir
		storage, err := processGitRedirectFile(commondirpath, "")
		if err == nil {
			return storage
		}
	}
	return gitDir
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>change the version so pre-releases don't look like 0.5.x releases<commit_after>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const (
	Version            = "0.6.0-pre"
	tempDirPerms       = 0755
	localMediaDirPerms = 0755
	localLogDirPerms   = 0755
)

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	GitCommit          string
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string // parent of index / config / hooks etc
	LocalGitStorageDir string // parent of objects/lfs (may be same as LocalGitDir but may not)
	LocalMediaDir      string // root of lfs objects
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func localMediaDirNoCreate(sha string) string {
	return filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
}
func localMediaPathNoCreate(sha string) string {
	return filepath.Join(localMediaDirNoCreate(sha), sha)
}

func LocalMediaPath(sha string) (string, error) {
	path := localMediaDirNoCreate(sha)
	if err := os.MkdirAll(path, localMediaDirPerms); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func ObjectExistsOfSize(sha string, size int64) bool {
	path := localMediaPathNoCreate(sha)
	return FileExistsOfSize(path, size)
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 0, len(osEnviron)+7)
	env = append(env,
		fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir),
		fmt.Sprintf("LocalGitDir=%s", LocalGitDir),
		fmt.Sprintf("LocalGitStorageDir=%s", LocalGitStorageDir),
		fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir),
		fmt.Sprintf("TempDir=%s", TempDir),
		fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers()),
		fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer()),
	)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalGitStorageDir = resolveGitStorageDir(LocalGitDir)
		LocalMediaDir = filepath.Join(LocalGitStorageDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp") // temp files per worktree

		if err := os.MkdirAll(LocalMediaDir, localMediaDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, localLogDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	gitCommit := ""
	if len(GitCommit) > 0 {
		gitCommit = "; git " + GitCommit
	}
	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s%s)",
		Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1),
		gitCommit,
	)
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTreeVar(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTreeVar(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTreeVar(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	return processGitRedirectFile(file, gitPtrPrefix)
}

func processGitRedirectFile(file, prefix string) (string, error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return "", err
	}

	contents := string(data)
	var dir string
	if len(prefix) > 0 {
		if !strings.HasPrefix(contents, prefix) {
			// Prefix required & not found
			return "", nil
		}
		dir = strings.TrimSpace(contents[len(prefix):])
	} else {
		dir = strings.TrimSpace(contents)
	}

	if !filepath.IsAbs(dir) {
		// The .git file contains a relative path.
		// Create an absolute path based on the directory the .git file is located in.
		dir = filepath.Join(filepath.Dir(file), dir)
	}

	return dir, nil
}

// From a git dir, get the location that objects are to be stored (we will store lfs alongside)
// Sometimes there is an additional level of redirect on the .git folder by way of a commondir file
// before you find object storage, e.g. 'git worktree' uses this. It redirects to gitdir either by GIT_DIR
// (during setup) or .git/git-dir: (during use), but this only contains the index etc, the objects
// are found in another git dir via 'commondir'.
func resolveGitStorageDir(gitDir string) string {
	commondirpath := filepath.Join(gitDir, "commondir")
	if FileExists(commondirpath) && !DirExists(filepath.Join(gitDir, "objects")) {
		// no git-dir: prefix in commondir
		storage, err := processGitRedirectFile(commondirpath, "")
		if err == nil {
			return storage
		}
	}
	return gitDir
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Ben Johnson

// 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.

package testutil

import (
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"
	"testing"
)

// Assert fails the test if the condition is false.
func Assert(tb testing.TB, condition bool, msg string, v ...interface{}) {
	if !condition {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...)
		tb.FailNow()
	}
}

// Ok fails the test if an err is not nil.
func Ok(tb testing.TB, err error) {
	if err != nil {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d: unexpected error: %s\033[39m\n\n", filepath.Base(file), line, err.Error())
		tb.FailNow()
	}
}

// Equals fails the test if exp is not equal to act.
func Equals(tb testing.TB, exp, act interface{}) {
	if !reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
		tb.FailNow()
	}
}
<commit_msg>add a NotOk helper method in the testing package<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Ben Johnson

// 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.

package testutil

import (
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"
	"testing"
)

// Assert fails the test if the condition is false.
func Assert(tb testing.TB, condition bool, msg string, v ...interface{}) {
	if !condition {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...)
		tb.FailNow()
	}
}

// Ok fails the test if an err is not nil.
func Ok(tb testing.TB, err error) {
	if err != nil {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d: unexpected error: %s\033[39m\n\n", filepath.Base(file), line, err.Error())
		tb.FailNow()
	}
}

// NotOk fails the test if an err is nil.
func NotOk(tb testing.TB, err error) {
	if err == nil {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d: expected error, got nothing \033[39m\n\n", filepath.Base(file), line)
		tb.FailNow()
	}
}

// Equals fails the test if exp is not equal to act.
func Equals(tb testing.TB, exp, act interface{}) {
	if !reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
		tb.FailNow()
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package version

import (
	"strconv"
	"strings"
)

var version string = "0.32.1"

func Full() string {
	return version
}

func getSubVersion(v string, position int) int64 {
	arr := strings.Split(v, ".")
	if len(arr) < 3 {
		return 0
	}
	res, _ := strconv.ParseInt(arr[position], 10, 64)
	return res
}

func Proto(v string) int64 {
	return getSubVersion(v, 0)
}

func Major(v string) int64 {
	return getSubVersion(v, 1)
}

func Minor(v string) int64 {
	return getSubVersion(v, 2)
}

// add every case there if server will not accept client's protocol and return false
func Compat(client string) (ok bool, msg string) {
	if LessThan(client, "0.18.0") {
		return false, "Please upgrade your frpc version to at least 0.18.0"
	}
	return true, ""
}

func LessThan(client string, server string) bool {
	vc := Proto(client)
	vs := Proto(server)
	if vc > vs {
		return false
	} else if vc < vs {
		return true
	}

	vc = Major(client)
	vs = Major(server)
	if vc > vs {
		return false
	} else if vc < vs {
		return true
	}

	vc = Minor(client)
	vs = Minor(server)
	if vc > vs {
		return false
	} else if vc < vs {
		return true
	}
	return false
}
<commit_msg>bump version to v0.33.0<commit_after>// Copyright 2016 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package version

import (
	"strconv"
	"strings"
)

var version string = "0.33.0"

func Full() string {
	return version
}

func getSubVersion(v string, position int) int64 {
	arr := strings.Split(v, ".")
	if len(arr) < 3 {
		return 0
	}
	res, _ := strconv.ParseInt(arr[position], 10, 64)
	return res
}

func Proto(v string) int64 {
	return getSubVersion(v, 0)
}

func Major(v string) int64 {
	return getSubVersion(v, 1)
}

func Minor(v string) int64 {
	return getSubVersion(v, 2)
}

// add every case there if server will not accept client's protocol and return false
func Compat(client string) (ok bool, msg string) {
	if LessThan(client, "0.18.0") {
		return false, "Please upgrade your frpc version to at least 0.18.0"
	}
	return true, ""
}

func LessThan(client string, server string) bool {
	vc := Proto(client)
	vs := Proto(server)
	if vc > vs {
		return false
	} else if vc < vs {
		return true
	}

	vc = Major(client)
	vs = Major(server)
	if vc > vs {
		return false
	} else if vc < vs {
		return true
	}

	vc = Minor(client)
	vs = Minor(server)
	if vc > vs {
		return false
	} else if vc < vs {
		return true
	}
	return false
}
<|endoftext|>