<commit_before>// +build !windows

package liner

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

type nexter struct {
	r   rune
	err error
}

type State struct {
	commonState
	r        *bufio.Reader
	origMode termios
	next     <-chan nexter
	winch    chan os.Signal
	pending  []rune
}

// NewLiner initializes a new *State, and sets the terminal into raw mode. To
// restore the terminal to its previous state, call State.Close().
//
// Note if you are still using Go 1.0: NewLiner handles SIGWINCH, so it will
// leak a channel every time you call it. Therefore, it is recommened that you
// upgrade to a newer release of Go, or ensure that NewLiner is only called
// once.
func NewLiner() *State {
	bad := map[string]bool{"": true, "dumb": true, "cons25": true}
	var s State
	s.r = bufio.NewReader(os.Stdin)
	s.supported = !bad[strings.ToLower(os.Getenv("TERM"))]

	if s.supported {
		syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), getTermios, uintptr(unsafe.Pointer(&s.origMode)))
		mode := s.origMode
		mode.Iflag &^= icrnl | inpck | istrip | ixon
		mode.Cflag |= cs8
		mode.Lflag &^= syscall.ECHO | icanon | iexten
		syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), setTermios, uintptr(unsafe.Pointer(&mode)))

		winch := make(chan os.Signal, 1)
		signal.Notify(winch, syscall.SIGWINCH)
		s.winch = winch

		next := make(chan nexter)
		go func() {
			for {
				var n nexter
				n.r, _, n.err = s.r.ReadRune()
				next <- n
			}
		}()
		s.next = next
	}

	return &s
}

var timedOut = errors.New("timeout")

func (s *State) nextPending(timeout <-chan time.Time) (rune, error) {
	select {
	case thing := <-s.next:
		if thing.err != nil {
			return 0, thing.err
		}
		s.pending = append(s.pending, thing.r)
		return thing.r, nil
	case <-timeout:
		rv := s.pending[0]
		s.pending = s.pending[1:]
		return rv, timedOut
	}
	// not reached
	return 0, nil
}

func (s *State) readNext() (interface{}, error) {
	if len(s.pending) > 0 {
		rv := s.pending[0]
		s.pending = s.pending[1:]
		return rv, nil
	}
	var r rune
	select {
	case thing := <-s.next:
		if thing.err != nil {
			return nil, thing.err
		}
		r = thing.r
	case <-s.winch:
		s.getColumns()
		return winch, nil
	}
	if r != esc {
		return r, nil
	}
	s.pending = append(s.pending, r)

	// Wait at most 50 ms for the rest of the escape sequence
	// If nothing else arrives, it was an actual press of the esc key
	timeout := time.After(50 * time.Millisecond)
	flag, err := s.nextPending(timeout)
	if err != nil {
		if err == timedOut {
			return flag, nil
		}
		return unknown, err
	}

	switch flag {
	case '[':
		code, err := s.nextPending(timeout)
		if err != nil {
			if err == timedOut {
				return code, nil
			}
			return unknown, err
		}
		switch code {
		case 'A':
			s.pending = s.pending[:0] // escape code complete
			return up, nil
		case 'B':
			s.pending = s.pending[:0] // escape code complete
			return down, nil
		case 'C':
			s.pending = s.pending[:0] // escape code complete
			return right, nil
		case 'D':
			s.pending = s.pending[:0] // escape code complete
			return left, nil
		case 'Z':
			s.pending = s.pending[:0] // escape code complete
			return shiftTab, nil
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			num := []rune{code}
			for {
				code, err := s.nextPending(timeout)
				if err != nil {
					if err == timedOut {
						return code, nil
					}
					return nil, err
				}
				switch code {
				case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
					num = append(num, code)
				case ';':
					// Modifier code to follow
					// This only supports Ctrl-left and Ctrl-right for now
					x, _ := strconv.ParseInt(string(num), 10, 32)
					if x != 1 {
						// Can't be left or right
						rv := s.pending[0]
						s.pending = s.pending[1:]
						return rv, nil
					}
					num = num[:0]
					for {
						code, err = s.nextPending(timeout)
						if err != nil {
							if err == timedOut {
								rv := s.pending[0]
								s.pending = s.pending[1:]
								return rv, nil
							}
							return nil, err
						}
						switch code {
						case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
							num = append(num, code)
						case 'C', 'D':
							// right, left
							mod, _ := strconv.ParseInt(string(num), 10, 32)
							if mod != 5 {
								// Not bare Ctrl
								rv := s.pending[0]
								s.pending = s.pending[1:]
								return rv, nil
							}
							s.pending = s.pending[:0] // escape code complete
							if code == 'C' {
								return wordRight, nil
							}
							return wordLeft, nil
						default:
							// Not left or right
							rv := s.pending[0]
							s.pending = s.pending[1:]
							return rv, nil
						}
					}
				case '~':
					s.pending = s.pending[:0] // escape code complete
					x, _ := strconv.ParseInt(string(num), 10, 32)
					switch x {
					case 2:
						return insert, nil
					case 3:
						return del, nil
					case 5:
						return pageUp, nil
					case 6:
						return pageDown, nil
					case 15:
						return f5, nil
					case 17:
						return f6, nil
					case 18:
						return f7, nil
					case 19:
						return f8, nil
					case 20:
						return f9, nil
					case 21:
						return f10, nil
					case 23:
						return f11, nil
					case 24:
						return f12, nil
					default:
						return unknown, nil
					}
				default:
					// unrecognized escape code
					rv := s.pending[0]
					s.pending = s.pending[1:]
					return rv, nil
				}
			}
		}

	case 'O':
		code, err := s.nextPending(timeout)
		if err != nil {
			if err == timedOut {
				return code, nil
			}
			return nil, err
		}
		s.pending = s.pending[:0] // escape code complete
		switch code {
		case 'H':
			return home, nil
		case 'F':
			return end, nil
		case 'P':
			return f1, nil
		case 'Q':
			return f2, nil
		case 'R':
			return f3, nil
		case 'S':
			return f4, nil
		default:
			return unknown, nil
		}
	default:
		rv := s.pending[0]
		s.pending = s.pending[1:]
		return rv, nil
	}

	// not reached
	return r, nil
}

func (s *State) promptUnsupported(p string) (string, error) {
	fmt.Print(p)
	linebuf, _, err := s.r.ReadLine()
	if err != nil {
		return "", err
	}
	return string(bytes.TrimSpace(linebuf)), nil
}

// Close returns the terminal to its previous mode
func (s *State) Close() error {
	stopSignal(s.winch)
	if s.supported {
		syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), setTermios, uintptr(unsafe.Pointer(&s.origMode)))
	}
	return nil
}
<commit_msg>golint: Document State<commit_after>// +build !windows

package liner

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

type nexter struct {
	r   rune
	err error
}

// State represents an open terminal
type State struct {
	commonState
	r        *bufio.Reader
	origMode termios
	next     <-chan nexter
	winch    chan os.Signal
	pending  []rune
}

// NewLiner initializes a new *State, and sets the terminal into raw mode. To
// restore the terminal to its previous state, call State.Close().
//
// Note if you are still using Go 1.0: NewLiner handles SIGWINCH, so it will
// leak a channel every time you call it. Therefore, it is recommened that you
// upgrade to a newer release of Go, or ensure that NewLiner is only called
// once.
func NewLiner() *State {
	bad := map[string]bool{"": true, "dumb": true, "cons25": true}
	var s State
	s.r = bufio.NewReader(os.Stdin)
	s.supported = !bad[strings.ToLower(os.Getenv("TERM"))]

	if s.supported {
		syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), getTermios, uintptr(unsafe.Pointer(&s.origMode)))
		mode := s.origMode
		mode.Iflag &^= icrnl | inpck | istrip | ixon
		mode.Cflag |= cs8
		mode.Lflag &^= syscall.ECHO | icanon | iexten
		syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), setTermios, uintptr(unsafe.Pointer(&mode)))

		winch := make(chan os.Signal, 1)
		signal.Notify(winch, syscall.SIGWINCH)
		s.winch = winch

		next := make(chan nexter)
		go func() {
			for {
				var n nexter
				n.r, _, n.err = s.r.ReadRune()
				next <- n
			}
		}()
		s.next = next
	}

	return &s
}

var timedOut = errors.New("timeout")

func (s *State) nextPending(timeout <-chan time.Time) (rune, error) {
	select {
	case thing := <-s.next:
		if thing.err != nil {
			return 0, thing.err
		}
		s.pending = append(s.pending, thing.r)
		return thing.r, nil
	case <-timeout:
		rv := s.pending[0]
		s.pending = s.pending[1:]
		return rv, timedOut
	}
	// not reached
	return 0, nil
}

func (s *State) readNext() (interface{}, error) {
	if len(s.pending) > 0 {
		rv := s.pending[0]
		s.pending = s.pending[1:]
		return rv, nil
	}
	var r rune
	select {
	case thing := <-s.next:
		if thing.err != nil {
			return nil, thing.err
		}
		r = thing.r
	case <-s.winch:
		s.getColumns()
		return winch, nil
	}
	if r != esc {
		return r, nil
	}
	s.pending = append(s.pending, r)

	// Wait at most 50 ms for the rest of the escape sequence
	// If nothing else arrives, it was an actual press of the esc key
	timeout := time.After(50 * time.Millisecond)
	flag, err := s.nextPending(timeout)
	if err != nil {
		if err == timedOut {
			return flag, nil
		}
		return unknown, err
	}

	switch flag {
	case '[':
		code, err := s.nextPending(timeout)
		if err != nil {
			if err == timedOut {
				return code, nil
			}
			return unknown, err
		}
		switch code {
		case 'A':
			s.pending = s.pending[:0] // escape code complete
			return up, nil
		case 'B':
			s.pending = s.pending[:0] // escape code complete
			return down, nil
		case 'C':
			s.pending = s.pending[:0] // escape code complete
			return right, nil
		case 'D':
			s.pending = s.pending[:0] // escape code complete
			return left, nil
		case 'Z':
			s.pending = s.pending[:0] // escape code complete
			return shiftTab, nil
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			num := []rune{code}
			for {
				code, err := s.nextPending(timeout)
				if err != nil {
					if err == timedOut {
						return code, nil
					}
					return nil, err
				}
				switch code {
				case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
					num = append(num, code)
				case ';':
					// Modifier code to follow
					// This only supports Ctrl-left and Ctrl-right for now
					x, _ := strconv.ParseInt(string(num), 10, 32)
					if x != 1 {
						// Can't be left or right
						rv := s.pending[0]
						s.pending = s.pending[1:]
						return rv, nil
					}
					num = num[:0]
					for {
						code, err = s.nextPending(timeout)
						if err != nil {
							if err == timedOut {
								rv := s.pending[0]
								s.pending = s.pending[1:]
								return rv, nil
							}
							return nil, err
						}
						switch code {
						case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
							num = append(num, code)
						case 'C', 'D':
							// right, left
							mod, _ := strconv.ParseInt(string(num), 10, 32)
							if mod != 5 {
								// Not bare Ctrl
								rv := s.pending[0]
								s.pending = s.pending[1:]
								return rv, nil
							}
							s.pending = s.pending[:0] // escape code complete
							if code == 'C' {
								return wordRight, nil
							}
							return wordLeft, nil
						default:
							// Not left or right
							rv := s.pending[0]
							s.pending = s.pending[1:]
							return rv, nil
						}
					}
				case '~':
					s.pending = s.pending[:0] // escape code complete
					x, _ := strconv.ParseInt(string(num), 10, 32)
					switch x {
					case 2:
						return insert, nil
					case 3:
						return del, nil
					case 5:
						return pageUp, nil
					case 6:
						return pageDown, nil
					case 15:
						return f5, nil
					case 17:
						return f6, nil
					case 18:
						return f7, nil
					case 19:
						return f8, nil
					case 20:
						return f9, nil
					case 21:
						return f10, nil
					case 23:
						return f11, nil
					case 24:
						return f12, nil
					default:
						return unknown, nil
					}
				default:
					// unrecognized escape code
					rv := s.pending[0]
					s.pending = s.pending[1:]
					return rv, nil
				}
			}
		}

	case 'O':
		code, err := s.nextPending(timeout)
		if err != nil {
			if err == timedOut {
				return code, nil
			}
			return nil, err
		}
		s.pending = s.pending[:0] // escape code complete
		switch code {
		case 'H':
			return home, nil
		case 'F':
			return end, nil
		case 'P':
			return f1, nil
		case 'Q':
			return f2, nil
		case 'R':
			return f3, nil
		case 'S':
			return f4, nil
		default:
			return unknown, nil
		}
	default:
		rv := s.pending[0]
		s.pending = s.pending[1:]
		return rv, nil
	}

	// not reached
	return r, nil
}

func (s *State) promptUnsupported(p string) (string, error) {
	fmt.Print(p)
	linebuf, _, err := s.r.ReadLine()
	if err != nil {
		return "", err
	}
	return string(bytes.TrimSpace(linebuf)), nil
}

// Close returns the terminal to its previous mode
func (s *State) Close() error {
	stopSignal(s.winch)
	if s.supported {
		syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), setTermios, uintptr(unsafe.Pointer(&s.origMode)))
	}
	return nil
}
<|endoftext|>


<commit_before>package http_crawler_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"

	. "github.com/alphagov/govuk_crawler_worker/http_crawler"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func testServer(status int, body string) *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(status)
		fmt.Fprintln(w, body)
	}))
}

var _ = Describe("Crawl", func() {
	var (
		crawler    *Crawler
		crawlerErr error
	)

	BeforeEach(func() {
		crawler, crawlerErr = NewCrawler("http://127.0.0.1/")

		Expect(crawlerErr).To(BeNil())
		Expect(crawler).ToNot(BeNil())
	})

	Describe("RetryStatusCodes", func() {
		It("should return a fixed int array with values 429, 500..599", func() {
			statusCodes := RetryStatusCodes()

			Expect(len(statusCodes)).To(Equal(101))
			Expect(statusCodes[0]).To(Equal(429))
			Expect(statusCodes[1]).To(Equal(500))
			Expect(statusCodes[100]).To(Equal(599))
		})
	})

	Describe("NewCrawler()", func() {
		It("doesn't allow providing empty URLs", func() {
			badCrawler, err := NewCrawler("")

			Expect(err).ToNot(BeNil())
			Expect(badCrawler).To(BeNil())
		})

		It("provides a new crawler that accepts the provided host", func() {
			GOVUKCrawler, err := NewCrawler("https://www.gov.uk/")

			Expect(err).To(BeNil())
			Expect(GOVUKCrawler.RootURL.Host).To(Equal("www.gov.uk"))
		})
	})

	Describe("Crawler.Crawl()", func() {
		It("specifies a user agent when making a request", func() {
			testServer := func(httpStatus int) *httptest.Server {
				return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					w.WriteHeader(httpStatus)
					fmt.Fprintln(w, r.UserAgent())
				}))
			}

			ts := testServer(http.StatusOK)
			defer ts.Close()

			body, err := crawler.Crawl(ts.URL)

			Expect(err).To(BeNil())
			Expect(strings.HasPrefix((string(body)), "GOV.UK Crawler Worker")).To(BeTrue())
		})

		It("returns a body with no errors for 200 OK responses", func() {
			ts := testServer(http.StatusOK, "Hello world")
			defer ts.Close()

			body, err := crawler.Crawl(ts.URL)

			Expect(err).To(BeNil())
			Expect(strings.TrimSpace(string(body))).To(Equal("Hello world"))
		})

		It("doesn't allow crawling a URL that doesn't match the root URL", func() {
			body, err := crawler.Crawl("http://google.com/foo")

			Expect(err).To(Equal(CannotCrawlURL))
			Expect(body).To(Equal([]byte{}))
		})

		Describe("returning a retry error", func() {
			It("returns a retry error if we get a response code of Too Many Requests", func() {
				ts := testServer(429, "Too Many Requests")
				defer ts.Close()

				body, err := crawler.Crawl(ts.URL)

				Expect(err).To(Equal(RetryRequestError))
				Expect(body).To(Equal([]byte{}))
			})

			It("returns a retry error if we get a response code of Internal Server Error", func() {
				ts := testServer(http.StatusInternalServerError, "Internal Server Error")
				defer ts.Close()

				body, err := crawler.Crawl(ts.URL)

				Expect(err).To(Equal(RetryRequestError))
				Expect(body).To(Equal([]byte{}))
			})

			It("returns a retry error if we get a response code of Gateway Timeout", func() {
				ts := testServer(http.StatusGatewayTimeout, "Gateway Timeout")
				defer ts.Close()

				body, err := crawler.Crawl(ts.URL)

				Expect(err).To(Equal(RetryRequestError))
				Expect(body).To(Equal([]byte{}))
			})
		})
	})
})
<commit_msg>Rename testServer for user agent test<commit_after>package http_crawler_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"

	. "github.com/alphagov/govuk_crawler_worker/http_crawler"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func testServer(status int, body string) *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(status)
		fmt.Fprintln(w, body)
	}))
}

var _ = Describe("Crawl", func() {
	var (
		crawler    *Crawler
		crawlerErr error
	)

	BeforeEach(func() {
		crawler, crawlerErr = NewCrawler("http://127.0.0.1/")

		Expect(crawlerErr).To(BeNil())
		Expect(crawler).ToNot(BeNil())
	})

	Describe("RetryStatusCodes", func() {
		It("should return a fixed int array with values 429, 500..599", func() {
			statusCodes := RetryStatusCodes()

			Expect(len(statusCodes)).To(Equal(101))
			Expect(statusCodes[0]).To(Equal(429))
			Expect(statusCodes[1]).To(Equal(500))
			Expect(statusCodes[100]).To(Equal(599))
		})
	})

	Describe("NewCrawler()", func() {
		It("doesn't allow providing empty URLs", func() {
			badCrawler, err := NewCrawler("")

			Expect(err).ToNot(BeNil())
			Expect(badCrawler).To(BeNil())
		})

		It("provides a new crawler that accepts the provided host", func() {
			GOVUKCrawler, err := NewCrawler("https://www.gov.uk/")

			Expect(err).To(BeNil())
			Expect(GOVUKCrawler.RootURL.Host).To(Equal("www.gov.uk"))
		})
	})

	Describe("Crawler.Crawl()", func() {
		It("specifies a user agent when making a request", func() {
			userAgentTestServer := func(httpStatus int) *httptest.Server {
				return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					w.WriteHeader(httpStatus)
					fmt.Fprintln(w, r.UserAgent())
				}))
			}

			ts := userAgentTestServer(http.StatusOK)
			defer ts.Close()

			body, err := crawler.Crawl(ts.URL)

			Expect(err).To(BeNil())
			Expect(strings.HasPrefix((string(body)), "GOV.UK Crawler Worker")).To(BeTrue())
		})

		It("returns a body with no errors for 200 OK responses", func() {
			ts := testServer(http.StatusOK, "Hello world")
			defer ts.Close()

			body, err := crawler.Crawl(ts.URL)

			Expect(err).To(BeNil())
			Expect(strings.TrimSpace(string(body))).To(Equal("Hello world"))
		})

		It("doesn't allow crawling a URL that doesn't match the root URL", func() {
			body, err := crawler.Crawl("http://google.com/foo")

			Expect(err).To(Equal(CannotCrawlURL))
			Expect(body).To(Equal([]byte{}))
		})

		Describe("returning a retry error", func() {
			It("returns a retry error if we get a response code of Too Many Requests", func() {
				ts := testServer(429, "Too Many Requests")
				defer ts.Close()

				body, err := crawler.Crawl(ts.URL)

				Expect(err).To(Equal(RetryRequestError))
				Expect(body).To(Equal([]byte{}))
			})

			It("returns a retry error if we get a response code of Internal Server Error", func() {
				ts := testServer(http.StatusInternalServerError, "Internal Server Error")
				defer ts.Close()

				body, err := crawler.Crawl(ts.URL)

				Expect(err).To(Equal(RetryRequestError))
				Expect(body).To(Equal([]byte{}))
			})

			It("returns a retry error if we get a response code of Gateway Timeout", func() {
				ts := testServer(http.StatusGatewayTimeout, "Gateway Timeout")
				defer ts.Close()

				body, err := crawler.Crawl(ts.URL)

				Expect(err).To(Equal(RetryRequestError))
				Expect(body).To(Equal([]byte{}))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/github.com/fatih/color"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/gopkg.in/yaml.v2"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"io/ioutil"
	"path/filepath"
	"regexp"
)

type Hound struct {
	Config string
	Fails  []string `yaml:"fail"`
	Warns  []string `yaml:"warn"`
	Skips  []string `yaml:"skip"`
}

// New innitializes a new Hound instance by parsing regexp patterns from a
// local configuration file to prepare for diff sniffing
func (h *Hound) New() (bool, error) {
	config, err := h.LoadConfig()
	if err != nil {
		return false, err
	}

	err = h.Parse(config)
	if err != nil {
		return false, err
	}

	return true, nil
}

// LoadConfig loads a local configuration file of regexp patterns
func (h *Hound) LoadConfig() ([]byte, error) {
	filename, _ := filepath.Abs(h.Config)
	return ioutil.ReadFile(filename)
}

// Parse parses a configuration byte array
func (h *Hound) Parse(data []byte) error {
	return yaml.Unmarshal(data, h)
}

// Sniff matches the passed git-diff hunk against all regexp patterns that
// were parsed from the local configuration
func (h *Hound) Sniff(fileName string, hunk *diff.Hunk) error {
	r1, _ := regexp.Compile(`^\w+\/`)
	fileName = r1.ReplaceAllString(fileName, "")
	if _, ok := h.MatchPatterns(h.Skips, []byte(fileName)); ok {
		return nil
	}

	r2, _ := regexp.Compile(`(?m)^\+\s*(.+)$`)
	matches := r2.FindAllSubmatch(hunk.Body, -1)

	for _, match := range matches {
		line := match[1]

		if pattern, ok := h.MatchPatterns(h.Warns, line); ok {
			message := color.YellowString(fmt.Sprintf("Warning: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			fmt.Print(message)
		}

		if pattern, ok := h.MatchPatterns(h.Fails, line); ok {
			err := color.RedString(fmt.Sprintf("Failure: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			return errors.New(err)
		}
	}

	return nil
}

// Match matches a byte array against a regexp pattern
func (h *Hound) Match(pattern string, subject []byte) (bool, error) {
	r, err := regexp.Compile(pattern)
	if err != nil {
		return false, err
	}

	if r.Match(subject) {
		return true, nil
	}

	return false, nil
}

// MatchPatterns matches a byte array against an array of regexp patterns
func (h *Hound) MatchPatterns(patterns []string, subject []byte) (string, bool) {
	for _, pattern := range patterns {
		if match, _ := h.Match(pattern, subject); match {
			return pattern, true
		}
	}

	return "", false
}
<commit_msg>fix spelling mistake<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/github.com/fatih/color"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/gopkg.in/yaml.v2"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"io/ioutil"
	"path/filepath"
	"regexp"
)

type Hound struct {
	Config string
	Fails  []string `yaml:"fail"`
	Warns  []string `yaml:"warn"`
	Skips  []string `yaml:"skip"`
}

// New initializes a new Hound instance by parsing regexp patterns from a
// local configuration file to prepare for diff sniffing
func (h *Hound) New() (bool, error) {
	config, err := h.LoadConfig()
	if err != nil {
		return false, err
	}

	err = h.Parse(config)
	if err != nil {
		return false, err
	}

	return true, nil
}

// LoadConfig loads a local configuration file of regexp patterns
func (h *Hound) LoadConfig() ([]byte, error) {
	filename, _ := filepath.Abs(h.Config)
	return ioutil.ReadFile(filename)
}

// Parse parses a configuration byte array
func (h *Hound) Parse(data []byte) error {
	return yaml.Unmarshal(data, h)
}

// Sniff matches the passed git-diff hunk against all regexp patterns that
// were parsed from the local configuration
func (h *Hound) Sniff(fileName string, hunk *diff.Hunk) error {
	r1, _ := regexp.Compile(`^\w+\/`)
	fileName = r1.ReplaceAllString(fileName, "")
	if _, ok := h.MatchPatterns(h.Skips, []byte(fileName)); ok {
		return nil
	}

	r2, _ := regexp.Compile(`(?m)^\+\s*(.+)$`)
	matches := r2.FindAllSubmatch(hunk.Body, -1)

	for _, match := range matches {
		line := match[1]

		if pattern, ok := h.MatchPatterns(h.Warns, line); ok {
			message := color.YellowString(fmt.Sprintf("Warning: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			fmt.Print(message)
		}

		if pattern, ok := h.MatchPatterns(h.Fails, line); ok {
			err := color.RedString(fmt.Sprintf("Failure: pattern `%s` match found for `%s` starting at line %d in %s\n",
				pattern, line, hunk.NewStartLine, fileName))
			return errors.New(err)
		}
	}

	return nil
}

// Match matches a byte array against a regexp pattern
func (h *Hound) Match(pattern string, subject []byte) (bool, error) {
	r, err := regexp.Compile(pattern)
	if err != nil {
		return false, err
	}

	if r.Match(subject) {
		return true, nil
	}

	return false, nil
}

// MatchPatterns matches a byte array against an array of regexp patterns
func (h *Hound) MatchPatterns(patterns []string, subject []byte) (string, bool) {
	for _, pattern := range patterns {
		if match, _ := h.Match(pattern, subject); match {
			return pattern, true
		}
	}

	return "", false
}
<|endoftext|>


<commit_before>package namespaces

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/dotcloud/docker/execdriver"
	"github.com/dotcloud/docker/execdriver/lxc"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
)

const (
	DriverName = "namespaces"
	Version    = "0.1"
)

var (
	ErrNotSupported = errors.New("not supported")
)

func init() {
	execdriver.RegisterInitFunc(DriverName, func(args *execdriver.InitArgs) error {
		var container *libcontainer.Container
		f, err := os.Open("container.json")
		if err != nil {
			return err
		}
		if err := json.NewDecoder(f).Decode(&container); err != nil {
			f.Close()
			return err
		}
		f.Close()

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(args.Pipe))
		if err != nil {
			return err
		}
		if err := nsinit.Init(container, cwd, args.Console, syncPipe, args.Args); err != nil {
			return err
		}
		return nil
	})
}

type driver struct {
	root string
}

type info struct {
	ID     string
	driver *driver
}

func (i *info) IsRunning() bool {
	p := filepath.Join(i.driver.root, "containers", i.ID, "rootfs", ".nspid")
	if _, err := os.Stat(p); err == nil {
		return true
	}
	return false
}

func NewDriver(root string) (*driver, error) {
	return &driver{
		root: root,
	}, nil
}

func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
	var (
		term        nsinit.Terminal
		container   = createContainer(c)
		factory     = &dockerCommandFactory{c}
		stateWriter = &dockerStateWriter{
			callback: startCallback,
			c:        c,
			dsw:      &nsinit.DefaultStateWriter{c.Rootfs},
		}
	)
	if c.Tty {
		term = &dockerTtyTerm{
			pipes: pipes,
		}
	} else {
		term = &dockerStdTerm{
			pipes: pipes,
		}
	}
	c.Terminal = term
	if err := writeContainerFile(container, c.Rootfs); err != nil {
		return -1, err
	}
	args := append([]string{c.Entrypoint}, c.Arguments...)
	return nsinit.Exec(container, factory, stateWriter, term, "", args)
}

func (d *driver) Kill(p *execdriver.Command, sig int) error {
	return p.Process.Kill()
}

func (d *driver) Restore(c *execdriver.Command) error {
	return ErrNotSupported
}

func (d *driver) Info(id string) execdriver.Info {
	return &info{
		ID:     id,
		driver: d,
	}
}

func (d *driver) Name() string {
	return fmt.Sprintf("%s-%s", DriverName, Version)
}

func (d *driver) GetPidsForContainer(id string) ([]int, error) {
	return nil, ErrNotSupported
}

func writeContainerFile(container *libcontainer.Container, rootfs string) error {
	data, err := json.Marshal(container)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filepath.Join(rootfs, "container.json"), data, 0755)
}

func getEnv(key string, env []string) string {
	for _, pair := range env {
		parts := strings.Split(pair, "=")
		if parts[0] == key {
			return parts[1]
		}
	}
	return ""
}

type dockerCommandFactory struct {
	c *execdriver.Command
}

// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func (d *dockerCommandFactory) Create(container *libcontainer.Container,
	console, logFile string, syncFd uintptr, args []string) *exec.Cmd {
	c := d.c
	// we need to join the rootfs because nsinit will setup the rootfs and chroot
	initPath := filepath.Join(c.Rootfs, c.InitPath)

	c.Path = initPath
	c.Args = append([]string{
		initPath,
		"-driver", DriverName,
		"-console", console,
		"-pipe", fmt.Sprint(syncFd),
		"-log", logFile,
	}, args...)
	c.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: uintptr(nsinit.GetNamespaceFlags(container.Namespaces)),
	}
	c.Env = container.Env
	c.Dir = c.Rootfs

	return &c.Cmd
}

type dockerStateWriter struct {
	dsw      nsinit.StateWriter
	c        *execdriver.Command
	callback execdriver.StartCallback
}

func (d *dockerStateWriter) WritePid(pid int) error {
	err := d.dsw.WritePid(pid)
	if d.callback != nil {
		d.callback(d.c)
	}
	return err
}

func (d *dockerStateWriter) DeletePid() error {
	return d.dsw.DeletePid()
}

func createContainer(c *execdriver.Command) *libcontainer.Container {
	container := getDefaultTemplate()

	container.Hostname = getEnv("HOSTNAME", c.Env)
	container.Tty = c.Tty
	container.User = c.User
	container.WorkingDir = c.WorkingDir
	container.Env = c.Env

	container.Env = append(container.Env, "container=docker")

	if c.Network != nil {
		container.Network = &libcontainer.Network{
			Mtu:     c.Network.Mtu,
			Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen),
			Gateway: c.Network.Gateway,
			Type:    "veth",
			Context: libcontainer.Context{
				"prefix": "dock",
				"bridge": c.Network.Bridge,
			},
		}
	}
	if c.Privileged {
		container.Capabilities = nil
	}
	if c.Resources != nil {
		container.Cgroups.CpuShares = c.Resources.CpuShares
		container.Cgroups.Memory = c.Resources.Memory
		container.Cgroups.MemorySwap = c.Resources.MemorySwap
	}
	return container
}

type dockerStdTerm struct {
	lxc.StdConsole
	pipes *execdriver.Pipes
}

func (d *dockerStdTerm) Attach(cmd *exec.Cmd) error {
	return d.AttachPipes(cmd, d.pipes)
}

func (d *dockerStdTerm) SetMaster(master *os.File) {
	// do nothing
}

type dockerTtyTerm struct {
	lxc.TtyConsole
	pipes *execdriver.Pipes
}

func (t *dockerTtyTerm) Attach(cmd *exec.Cmd) error {
	go io.Copy(t.pipes.Stdout, t.MasterPty)
	if t.pipes.Stdin != nil {
		go io.Copy(t.MasterPty, t.pipes.Stdin)
	}
	return nil
}

func (t *dockerTtyTerm) SetMaster(master *os.File) {
	t.MasterPty = master
}
<commit_msg>Fix kill signals and rootfs path for pid Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)<commit_after>package namespaces

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/dotcloud/docker/execdriver"
	"github.com/dotcloud/docker/execdriver/lxc"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
)

const (
	DriverName = "namespaces"
	Version    = "0.1"
)

var (
	ErrNotSupported = errors.New("not supported")
)

func init() {
	execdriver.RegisterInitFunc(DriverName, func(args *execdriver.InitArgs) error {
		var container *libcontainer.Container
		f, err := os.Open("container.json")
		if err != nil {
			return err
		}
		if err := json.NewDecoder(f).Decode(&container); err != nil {
			f.Close()
			return err
		}
		f.Close()

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(args.Pipe))
		if err != nil {
			return err
		}
		if err := nsinit.Init(container, cwd, args.Console, syncPipe, args.Args); err != nil {
			return err
		}
		return nil
	})
}

type driver struct {
	root string
}

type info struct {
	ID     string
	driver *driver
}

func (i *info) IsRunning() bool {
	p := filepath.Join(i.driver.root, "containers", i.ID, "root", ".nspid")
	if _, err := os.Stat(p); err == nil {
		return true
	}
	return false
}

func NewDriver(root string) (*driver, error) {
	return &driver{
		root: root,
	}, nil
}

func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
	var (
		term        nsinit.Terminal
		container   = createContainer(c)
		factory     = &dockerCommandFactory{c}
		stateWriter = &dockerStateWriter{
			callback: startCallback,
			c:        c,
			dsw:      &nsinit.DefaultStateWriter{c.Rootfs},
		}
	)
	if c.Tty {
		term = &dockerTtyTerm{
			pipes: pipes,
		}
	} else {
		term = &dockerStdTerm{
			pipes: pipes,
		}
	}
	c.Terminal = term
	if err := writeContainerFile(container, c.Rootfs); err != nil {
		return -1, err
	}
	args := append([]string{c.Entrypoint}, c.Arguments...)
	return nsinit.Exec(container, factory, stateWriter, term, "", args)
}

func (d *driver) Kill(p *execdriver.Command, sig int) error {
	return syscall.Kill(p.Process.Pid, syscall.Signal(sig))
}

func (d *driver) Restore(c *execdriver.Command) error {
	return ErrNotSupported
}

func (d *driver) Info(id string) execdriver.Info {
	return &info{
		ID:     id,
		driver: d,
	}
}

func (d *driver) Name() string {
	return fmt.Sprintf("%s-%s", DriverName, Version)
}

func (d *driver) GetPidsForContainer(id string) ([]int, error) {
	return nil, ErrNotSupported
}

func writeContainerFile(container *libcontainer.Container, rootfs string) error {
	data, err := json.Marshal(container)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filepath.Join(rootfs, "container.json"), data, 0755)
}

func getEnv(key string, env []string) string {
	for _, pair := range env {
		parts := strings.Split(pair, "=")
		if parts[0] == key {
			return parts[1]
		}
	}
	return ""
}

type dockerCommandFactory struct {
	c *execdriver.Command
}

// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func (d *dockerCommandFactory) Create(container *libcontainer.Container,
	console, logFile string, syncFd uintptr, args []string) *exec.Cmd {
	c := d.c
	// we need to join the rootfs because nsinit will setup the rootfs and chroot
	initPath := filepath.Join(c.Rootfs, c.InitPath)

	c.Path = initPath
	c.Args = append([]string{
		initPath,
		"-driver", DriverName,
		"-console", console,
		"-pipe", fmt.Sprint(syncFd),
		"-log", logFile,
	}, args...)
	c.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: uintptr(nsinit.GetNamespaceFlags(container.Namespaces)),
	}
	c.Env = container.Env
	c.Dir = c.Rootfs

	return &c.Cmd
}

type dockerStateWriter struct {
	dsw      nsinit.StateWriter
	c        *execdriver.Command
	callback execdriver.StartCallback
}

func (d *dockerStateWriter) WritePid(pid int) error {
	err := d.dsw.WritePid(pid)
	if d.callback != nil {
		d.callback(d.c)
	}
	return err
}

func (d *dockerStateWriter) DeletePid() error {
	return d.dsw.DeletePid()
}

func createContainer(c *execdriver.Command) *libcontainer.Container {
	container := getDefaultTemplate()

	container.Hostname = getEnv("HOSTNAME", c.Env)
	container.Tty = c.Tty
	container.User = c.User
	container.WorkingDir = c.WorkingDir
	container.Env = c.Env

	container.Env = append(container.Env, "container=docker")

	if c.Network != nil {
		container.Network = &libcontainer.Network{
			Mtu:     c.Network.Mtu,
			Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen),
			Gateway: c.Network.Gateway,
			Type:    "veth",
			Context: libcontainer.Context{
				"prefix": "dock",
				"bridge": c.Network.Bridge,
			},
		}
	}
	if c.Privileged {
		container.Capabilities = nil
	}
	if c.Resources != nil {
		container.Cgroups.CpuShares = c.Resources.CpuShares
		container.Cgroups.Memory = c.Resources.Memory
		container.Cgroups.MemorySwap = c.Resources.MemorySwap
	}
	return container
}

type dockerStdTerm struct {
	lxc.StdConsole
	pipes *execdriver.Pipes
}

func (d *dockerStdTerm) Attach(cmd *exec.Cmd) error {
	return d.AttachPipes(cmd, d.pipes)
}

func (d *dockerStdTerm) SetMaster(master *os.File) {
	// do nothing
}

type dockerTtyTerm struct {
	lxc.TtyConsole
	pipes *execdriver.Pipes
}

func (t *dockerTtyTerm) Attach(cmd *exec.Cmd) error {
	go io.Copy(t.pipes.Stdout, t.MasterPty)
	if t.pipes.Stdin != nil {
		go io.Copy(t.MasterPty, t.pipes.Stdin)
	}
	return nil
}

func (t *dockerTtyTerm) SetMaster(master *os.File) {
	t.MasterPty = master
}
<|endoftext|>


<commit_before>package namespaces

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/dotcloud/docker/execdriver"
	"github.com/dotcloud/docker/execdriver/lxc"
	"github.com/dotcloud/docker/pkg/cgroups"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

const (
	DriverName = "namespaces"
	Version    = "0.1"
)

var (
	ErrNotSupported = errors.New("not supported")
)

func init() {
	execdriver.RegisterInitFunc(DriverName, func(args *execdriver.InitArgs) error {
		var container *libcontainer.Container
		f, err := os.Open("container.json")
		if err != nil {
			return err
		}
		if err := json.NewDecoder(f).Decode(&container); err != nil {
			f.Close()
			return err
		}
		f.Close()

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(args.Pipe))
		if err != nil {
			return err
		}
		if err := nsinit.Init(container, cwd, args.Console, syncPipe, args.Args); err != nil {
			return err
		}
		return nil
	})
}

type driver struct {
	root string
}

type info struct {
	ID     string
	driver *driver
}

func (i *info) IsRunning() bool {
	p := filepath.Join(i.driver.root, "containers", i.ID, "root", ".nspid")
	if _, err := os.Stat(p); err == nil {
		return true
	}
	return false
}

func NewDriver(root string) (*driver, error) {
	return &driver{
		root: root,
	}, nil
}

func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
	var (
		term        nsinit.Terminal
		container   = createContainer(c)
		factory     = &dockerCommandFactory{c}
		stateWriter = &dockerStateWriter{
			callback: startCallback,
			c:        c,
			dsw:      &nsinit.DefaultStateWriter{c.Rootfs},
		}
	)
	if c.Tty {
		term = &dockerTtyTerm{
			pipes: pipes,
		}
	} else {
		term = &dockerStdTerm{
			pipes: pipes,
		}
	}
	c.Terminal = term
	if err := writeContainerFile(container, c.Rootfs); err != nil {
		return -1, err
	}
	args := append([]string{c.Entrypoint}, c.Arguments...)
	return nsinit.Exec(container, factory, stateWriter, term, "", args)
}

func (d *driver) Kill(p *execdriver.Command, sig int) error {
	return syscall.Kill(p.Process.Pid, syscall.Signal(sig))
}

func (d *driver) Restore(c *execdriver.Command) error {
	return ErrNotSupported
}

func (d *driver) Info(id string) execdriver.Info {
	return &info{
		ID:     id,
		driver: d,
	}
}

func (d *driver) Name() string {
	return fmt.Sprintf("%s-%s", DriverName, Version)
}

func (d *driver) GetPidsForContainer(id string) ([]int, error) {
	pids := []int{}

	subsystem := "devices"
	cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem)
	if err != nil {
		return pids, err
	}
	cgroupDir, err := cgroups.GetThisCgroupDir(subsystem)
	if err != nil {
		return pids, err
	}

	filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks")
	}

	output, err := ioutil.ReadFile(filename)
	if err != nil {
		return pids, err
	}
	for _, p := range strings.Split(string(output), "\n") {
		if len(p) == 0 {
			continue
		}
		pid, err := strconv.Atoi(p)
		if err != nil {
			return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
		}
		pids = append(pids, pid)
	}
	return pids, nil
}

func writeContainerFile(container *libcontainer.Container, rootfs string) error {
	data, err := json.Marshal(container)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filepath.Join(rootfs, "container.json"), data, 0755)
}

func getEnv(key string, env []string) string {
	for _, pair := range env {
		parts := strings.Split(pair, "=")
		if parts[0] == key {
			return parts[1]
		}
	}
	return ""
}

type dockerCommandFactory struct {
	c *execdriver.Command
}

// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func (d *dockerCommandFactory) Create(container *libcontainer.Container,
	console, logFile string, syncFd uintptr, args []string) *exec.Cmd {
	c := d.c
	// we need to join the rootfs because nsinit will setup the rootfs and chroot
	initPath := filepath.Join(c.Rootfs, c.InitPath)

	c.Path = initPath
	c.Args = append([]string{
		initPath,
		"-driver", DriverName,
		"-console", console,
		"-pipe", fmt.Sprint(syncFd),
		"-log", logFile,
	}, args...)
	c.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: uintptr(nsinit.GetNamespaceFlags(container.Namespaces)),
	}
	c.Env = container.Env
	c.Dir = c.Rootfs

	return &c.Cmd
}

type dockerStateWriter struct {
	dsw      nsinit.StateWriter
	c        *execdriver.Command
	callback execdriver.StartCallback
}

func (d *dockerStateWriter) WritePid(pid int) error {
	err := d.dsw.WritePid(pid)
	if d.callback != nil {
		d.callback(d.c)
	}
	return err
}

func (d *dockerStateWriter) DeletePid() error {
	return d.dsw.DeletePid()
}

func createContainer(c *execdriver.Command) *libcontainer.Container {
	container := getDefaultTemplate()

	container.Hostname = getEnv("HOSTNAME", c.Env)
	container.Tty = c.Tty
	container.User = c.User
	container.WorkingDir = c.WorkingDir
	container.Env = c.Env

	container.Env = append(container.Env, "container=docker")

	if c.Network != nil {
		container.Network = &libcontainer.Network{
			Mtu:     c.Network.Mtu,
			Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen),
			Gateway: c.Network.Gateway,
			Type:    "veth",
			Context: libcontainer.Context{
				"prefix": "dock",
				"bridge": c.Network.Bridge,
			},
		}
	}
	container.Cgroups.Name = c.ID
	if c.Privileged {
		container.Capabilities = nil
		container.Cgroups.DeviceAccess = true
	}
	if c.Resources != nil {
		container.Cgroups.CpuShares = c.Resources.CpuShares
		container.Cgroups.Memory = c.Resources.Memory
		container.Cgroups.MemorySwap = c.Resources.MemorySwap
	}
	return container
}

type dockerStdTerm struct {
	lxc.StdConsole
	pipes *execdriver.Pipes
}

func (d *dockerStdTerm) Attach(cmd *exec.Cmd) error {
	return d.AttachPipes(cmd, d.pipes)
}

func (d *dockerStdTerm) SetMaster(master *os.File) {
	// do nothing
}

type dockerTtyTerm struct {
	lxc.TtyConsole
	pipes *execdriver.Pipes
}

func (t *dockerTtyTerm) Attach(cmd *exec.Cmd) error {
	go io.Copy(t.pipes.Stdout, t.MasterPty)
	if t.pipes.Stdin != nil {
		go io.Copy(t.MasterPty, t.pipes.Stdin)
	}
	return nil
}

func (t *dockerTtyTerm) SetMaster(master *os.File) {
	t.MasterPty = master
}
<commit_msg>Fix restore container by nspid Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)<commit_after>package namespaces

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/dotcloud/docker/execdriver"
	"github.com/dotcloud/docker/execdriver/lxc"
	"github.com/dotcloud/docker/pkg/cgroups"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

const (
	DriverName = "namespaces"
	Version    = "0.1"
)

var (
	ErrNotSupported = errors.New("not supported")
)

func init() {
	execdriver.RegisterInitFunc(DriverName, func(args *execdriver.InitArgs) error {
		var container *libcontainer.Container
		f, err := os.Open("container.json")
		if err != nil {
			return err
		}
		if err := json.NewDecoder(f).Decode(&container); err != nil {
			f.Close()
			return err
		}
		f.Close()

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(args.Pipe))
		if err != nil {
			return err
		}
		if err := nsinit.Init(container, cwd, args.Console, syncPipe, args.Args); err != nil {
			return err
		}
		return nil
	})
}

type driver struct {
	root string
}

type info struct {
	ID     string
	driver *driver
}

func (i *info) IsRunning() bool {
	p := filepath.Join(i.driver.root, "containers", i.ID, "root", ".nspid")
	if _, err := os.Stat(p); err == nil {
		return true
	}
	return false
}

func NewDriver(root string) (*driver, error) {
	return &driver{
		root: root,
	}, nil
}

func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
	var (
		term        nsinit.Terminal
		container   = createContainer(c)
		factory     = &dockerCommandFactory{c}
		stateWriter = &dockerStateWriter{
			callback: startCallback,
			c:        c,
			dsw:      &nsinit.DefaultStateWriter{c.Rootfs},
		}
	)
	if c.Tty {
		term = &dockerTtyTerm{
			pipes: pipes,
		}
	} else {
		term = &dockerStdTerm{
			pipes: pipes,
		}
	}
	c.Terminal = term
	if err := writeContainerFile(container, c.Rootfs); err != nil {
		return -1, err
	}
	args := append([]string{c.Entrypoint}, c.Arguments...)
	return nsinit.Exec(container, factory, stateWriter, term, "", args)
}

func (d *driver) Kill(p *execdriver.Command, sig int) error {
	return syscall.Kill(p.Process.Pid, syscall.Signal(sig))
}

func (d *driver) Restore(c *execdriver.Command) error {
	var (
		nspid int
		p     = filepath.Join(d.root, "containers", c.ID, "root", ".nspid")
	)
	f, err := os.Open(p)
	if err != nil {
		return err
	}
	defer f.Close()
	if _, err := fmt.Fscanf(f, "%d", &nspid); err != nil {
		return err
	}
	proc, err := os.FindProcess(nspid)
	if err != nil {
		return err
	}
	_, err = proc.Wait()
	return err
}

func (d *driver) Info(id string) execdriver.Info {
	return &info{
		ID:     id,
		driver: d,
	}
}

func (d *driver) Name() string {
	return fmt.Sprintf("%s-%s", DriverName, Version)
}

func (d *driver) GetPidsForContainer(id string) ([]int, error) {
	pids := []int{}

	subsystem := "devices"
	cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem)
	if err != nil {
		return pids, err
	}
	cgroupDir, err := cgroups.GetThisCgroupDir(subsystem)
	if err != nil {
		return pids, err
	}

	filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks")
	}

	output, err := ioutil.ReadFile(filename)
	if err != nil {
		return pids, err
	}
	for _, p := range strings.Split(string(output), "\n") {
		if len(p) == 0 {
			continue
		}
		pid, err := strconv.Atoi(p)
		if err != nil {
			return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
		}
		pids = append(pids, pid)
	}
	return pids, nil
}

func writeContainerFile(container *libcontainer.Container, rootfs string) error {
	data, err := json.Marshal(container)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filepath.Join(rootfs, "container.json"), data, 0755)
}

func getEnv(key string, env []string) string {
	for _, pair := range env {
		parts := strings.Split(pair, "=")
		if parts[0] == key {
			return parts[1]
		}
	}
	return ""
}

type dockerCommandFactory struct {
	c *execdriver.Command
}

// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func (d *dockerCommandFactory) Create(container *libcontainer.Container,
	console, logFile string, syncFd uintptr, args []string) *exec.Cmd {
	c := d.c
	// we need to join the rootfs because nsinit will setup the rootfs and chroot
	initPath := filepath.Join(c.Rootfs, c.InitPath)

	c.Path = initPath
	c.Args = append([]string{
		initPath,
		"-driver", DriverName,
		"-console", console,
		"-pipe", fmt.Sprint(syncFd),
		"-log", logFile,
	}, args...)
	c.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: uintptr(nsinit.GetNamespaceFlags(container.Namespaces)),
	}
	c.Env = container.Env
	c.Dir = c.Rootfs

	return &c.Cmd
}

type dockerStateWriter struct {
	dsw      nsinit.StateWriter
	c        *execdriver.Command
	callback execdriver.StartCallback
}

func (d *dockerStateWriter) WritePid(pid int) error {
	err := d.dsw.WritePid(pid)
	if d.callback != nil {
		d.callback(d.c)
	}
	return err
}

func (d *dockerStateWriter) DeletePid() error {
	return d.dsw.DeletePid()
}

func createContainer(c *execdriver.Command) *libcontainer.Container {
	container := getDefaultTemplate()

	container.Hostname = getEnv("HOSTNAME", c.Env)
	container.Tty = c.Tty
	container.User = c.User
	container.WorkingDir = c.WorkingDir
	container.Env = c.Env

	container.Env = append(container.Env, "container=docker")

	if c.Network != nil {
		container.Network = &libcontainer.Network{
			Mtu:     c.Network.Mtu,
			Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen),
			Gateway: c.Network.Gateway,
			Type:    "veth",
			Context: libcontainer.Context{
				"prefix": "dock",
				"bridge": c.Network.Bridge,
			},
		}
	}
	container.Cgroups.Name = c.ID
	if c.Privileged {
		container.Capabilities = nil
		container.Cgroups.DeviceAccess = true
	}
	if c.Resources != nil {
		container.Cgroups.CpuShares = c.Resources.CpuShares
		container.Cgroups.Memory = c.Resources.Memory
		container.Cgroups.MemorySwap = c.Resources.MemorySwap
	}
	return container
}

type dockerStdTerm struct {
	lxc.StdConsole
	pipes *execdriver.Pipes
}

func (d *dockerStdTerm) Attach(cmd *exec.Cmd) error {
	return d.AttachPipes(cmd, d.pipes)
}

func (d *dockerStdTerm) SetMaster(master *os.File) {
	// do nothing
}

type dockerTtyTerm struct {
	lxc.TtyConsole
	pipes *execdriver.Pipes
}

func (t *dockerTtyTerm) Attach(cmd *exec.Cmd) error {
	go io.Copy(t.pipes.Stdout, t.MasterPty)
	if t.pipes.Stdin != nil {
		go io.Copy(t.MasterPty, t.pipes.Stdin)
	}
	return nil
}

func (t *dockerTtyTerm) SetMaster(master *os.File) {
	t.MasterPty = master
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
)

type IPAddress struct {
	IP string `json:"ip"`
}

func jsonip(w http.ResponseWriter, r *http.Request) {
	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()
	jsonStr, _ := json.Marshal(IPAddress{host})

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, string(jsonStr))
}

func textip(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		panic(err)
	}

	for k, _ := range r.Form {
		fmt.Println(k, r.Form[k][0])
	}
	fmt.Println(r.Form["hiya"][0])

	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()

	w.Header().Set("Content-Type", "text/plain")
	fmt.Fprintf(w, host)
}

func NotFound(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
}

func main() {
	http.HandleFunc("/json", jsonip)
	http.HandleFunc("/text", textip)

	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Adding package comments.<commit_after>// ipify-api
//
// This software implements a basic REST API that provides users with a simple
// way to query their public IP address (IPv4 or IPv6).  This code assumes that
// you are running it on Heroku's platform (https://www.heroku.com/).

package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
)

type IPAddress struct {
	IP string `json:"ip"`
}

func jsonip(w http.ResponseWriter, r *http.Request) {
	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()
	jsonStr, _ := json.Marshal(IPAddress{host})

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, string(jsonStr))
}

func textip(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		panic(err)
	}

	for k, _ := range r.Form {
		fmt.Println(k, r.Form[k][0])
	}
	fmt.Println(r.Form["hiya"][0])

	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()

	w.Header().Set("Content-Type", "text/plain")
	fmt.Fprintf(w, host)
}

func NotFound(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
}

func main() {
	http.HandleFunc("/json", jsonip)
	http.HandleFunc("/text", textip)

	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Package is provide utilities for identifying Unicode categories of runes, relating to Unicode text segmentation:
// https://unicode.org/reports/tr29/
package is

import "unicode"

// Alphabetic is defined here: https://unicode.org/reports/tr44/#Alphabetic
func Alphabetic(r rune) bool {
	switch {
	case
		r == '_',
		unicode.IsLetter(r),
		unicode.Is(unicode.Nl, r),
		unicode.Is(unicode.Other_Alphabetic, r):
		return true
	}
	return false
}

// ALetter is defined here: https://unicode.org/reports/tr29/#ALetter
func ALetter(r rune) bool {
	// Logic of the above standard, from the bottom up

	switch {
	case
		HebrewLetter(r),
		unicode.Is(unicode.Hiragana, r),
		unicode.Is(unicode.Katakana, r),
		unicode.Is(unicode.Ideographic, r):
		return false
	}

	if unicode.Is(ALetterTable, r) {
		return true
	}

	return Alphabetic(r)
}

var ALetterTable = &unicode.RangeTable{
	R16: []unicode.Range16{
		{0x02C2, 0x02C5, 1},
		{0x02D2, 0x02D7, 1},
		{0x02DE, 0x02DF, 1},
		{0x02E5, 0x02EB, 1},
		{0x02ED, 0x02ED, 1},
		{0x02EF, 0x02FF, 1},
		{0x055A, 0x055C, 1},
		{0x055E, 0x055E, 1},
		{0x058A, 0x058A, 1},
		{0x05F3, 0x05F3, 1},
		{0xA708, 0xA716, 1},
		{0xA720, 0xA721, 1},
		{0xA789, 0xA78A, 1},
		{0xAB5B, 0xAB5B, 1},
	},
}

// AHLetter is ALetter or HebrewLetter
func AHLetter(r rune) bool {
	return ALetter(r) || HebrewLetter(r)
}

// MidLetter is defined here: https://unicode.org/reports/tr29/#MidLetter
func MidLetter(r rune) bool {
	switch r {
	case
		//':',	// TODO Swedish
		'·',
		'·',
		'՟',
		'״',
		'‧',
		'︓',
		'﹕',
		'：':
		return true
	}
	return false
}

// MidNumLet is defined here: https://unicode.org/reports/tr29/#MidNumLet
func MidNumLet(r rune) bool {
	switch r {
	case
		'.',
		'’',
		'․',
		'﹒',
		'＇',
		'．':
		return true
	}
	return false
}

// MidNumLetQ is defined here: https://unicode.org/reports/tr29/#MidNumLet
func MidNumLetQ(r rune) bool {
	return MidNumLet(r) || r == '\''
}

// InfixNumeric is defined here: https://unicode.org/reports/tr14/
func InfixNumeric(r rune) bool {
	switch r {
	case
		0x002C,
		0x002E,
		0x003A,
		0x003B,
		0x037E,
		0x0589,
		0x060C,
		0x060D,
		0x07F8,
		0x2044,
		0xFE10,
		0xFE13,
		0xFE14:
		return true
	}

	return false
}

// MidNum is defined here: https://unicode.org/reports/tr29/#MidNum
func MidNum(r rune) bool {
	switch r {
	case
		0x003A,
		0xFE13,
		0x002E:
		return false
	case
		0x066C,
		0xFE50,
		0xFE54,
		0xFF0C,
		0xFF1B:
		return true
	default:
		return InfixNumeric(r)
	}
}

// Numeric is defined here: https://unicode.org/reports/tr29/#Numeric
func Numeric(r rune) bool {
	switch {
	case r == '٬':
		return false
	case 0xFF10 <= r && r <= 0xFF19:
		return true
	default:
		return unicode.IsNumber(r)
	}
}

// Cr is carriage return (\r, 13)
func Cr(r rune) bool {
	return r == '\r'
}

// Lf is line feed (\n, 10)
func Lf(r rune) bool {
	return r == '\n'
}

// Katakana is defined here: https://unicode.org/reports/tr29/#Katakana
func Katakana(r rune) bool {
	switch r {
	case
		0x3031,
		0x3032,
		0x3033,
		0x3034,
		0x3035,
		0x309B,
		0x309C,
		0x30A0,
		0x30FC,
		0xFF70:
		return true
	default:
		return unicode.Is(unicode.Katakana, r)
	}
}

// HebrewLetter is defined here: https://unicode.org/reports/tr29/#Hebrew_Letter
func HebrewLetter(r rune) bool {
	return unicode.Is(unicode.Hebrew, r) && unicode.IsLetter(r)
}

// Newline is defined here: https://unicode.org/reports/tr29/#WB3a
func Newline(r rune) bool {
	switch r {
	case
		0x000B,
		0x000C,
		0x0085,
		0x2028,
		0x2029:
		return true
	}

	return false
}

// SingleQuote is defined here: https://unicode.org/reports/tr29/#Single_Quote
func SingleQuote(r rune) bool {
	return r == '\''
}

// DoubleQuote is defined here: https://unicode.org/reports/tr29/#Double_Quote
func DoubleQuote(r rune) bool {
	return r == '"'
}

// WSegSpace is defined here: https://unicode.org/reports/tr29/#WSegSpace
func WSegSpace(r rune) bool {
	return unicode.Is(unicode.Zs, r)
}

// ExtendNumLet is defined here: https://unicode.org/reports/tr29/#ExtendNumLetWB
func ExtendNumLet(r rune) bool {
	return unicode.Is(unicode.Pc, r) || r == 0x202F
}
<commit_msg>Use more range tables<commit_after>// Package is provide utilities for identifying Unicode categories of runes, relating to Unicode text segmentation:
// https://unicode.org/reports/tr29/
package is

import (
	"unicode"

	"golang.org/x/text/unicode/rangetable"
)

// Alphabetic is defined here: https://unicode.org/reports/tr44/#Alphabetic
func Alphabetic(r rune) bool {
	switch {
	case
		r == '_',
		unicode.IsLetter(r),
		unicode.Is(unicode.Nl, r),
		unicode.Is(unicode.Other_Alphabetic, r):
		return true
	}
	return false
}

// ALetter is defined here: https://unicode.org/reports/tr29/#ALetter
func ALetter(r rune) bool {
	// Logic of the above standard, from the bottom up

	switch {
	case
		HebrewLetter(r),
		unicode.Is(unicode.Hiragana, r),
		unicode.Is(unicode.Katakana, r),
		unicode.Is(unicode.Ideographic, r):
		return false
	}

	if unicode.Is(ALetterTable, r) {
		return true
	}

	return Alphabetic(r)
}

var ALetterTable = &unicode.RangeTable{
	R16: []unicode.Range16{
		{0x02C2, 0x02C5, 1},
		{0x02D2, 0x02D7, 1},
		{0x02DE, 0x02DF, 1},
		{0x02E5, 0x02EB, 1},
		{0x02ED, 0x02ED, 1},
		{0x02EF, 0x02FF, 1},
		{0x055A, 0x055C, 1},
		{0x055E, 0x055E, 1},
		{0x058A, 0x058A, 1},
		{0x05F3, 0x05F3, 1},
		{0xA708, 0xA716, 1},
		{0xA720, 0xA721, 1},
		{0xA789, 0xA78A, 1},
		{0xAB5B, 0xAB5B, 1},
	},
}

// AHLetter is ALetter or HebrewLetter
func AHLetter(r rune) bool {
	return ALetter(r) || HebrewLetter(r)
}

var midLetter = rangetable.New(
	//':',	// TODO Swedish
	'·',
	'·',
	'՟',
	'״',
	'‧',
	'︓',
	'﹕',
	'：',
)

// MidLetter is defined here: https://unicode.org/reports/tr29/#MidLetter
func MidLetter(r rune) bool {
	return unicode.Is(midLetter, r)
}

var midNumLet = rangetable.New(
	'.',
	'’',
	'․',
	'﹒',
	'＇',
	'．',
)

// MidNumLet is defined here: https://unicode.org/reports/tr29/#MidNumLet
func MidNumLet(r rune) bool {
	return unicode.Is(midNumLet, r)
}

// MidNumLetQ is defined here: https://unicode.org/reports/tr29/#MidNumLet
func MidNumLetQ(r rune) bool {
	return MidNumLet(r) || r == '\''
}

var infixNumeric = rangetable.New(
	0x002C,
	0x002E,
	0x003A,
	0x003B,
	0x037E,
	0x0589,
	0x060C,
	0x060D,
	0x07F8,
	0x2044,
	0xFE10,
	0xFE13,
	0xFE14,
)

// InfixNumeric is defined here: https://unicode.org/reports/tr14/
func InfixNumeric(r rune) bool {
	return unicode.Is(infixNumeric, r)
}

var notMidNum = rangetable.New(
	0x003A,
	0xFE13,
	0x002E,
)

var addMidNum = rangetable.New(
	0x066C,
	0xFE50,
	0xFE54,
	0xFF0C,
	0xFF1B,
)

// MidNum is defined here: https://unicode.org/reports/tr29/#MidNum
func MidNum(r rune) bool {
	return !unicode.Is(notMidNum, r) && (InfixNumeric(r) || unicode.Is(addMidNum, r))
}

// Numeric is defined here: https://unicode.org/reports/tr29/#Numeric
func Numeric(r rune) bool {
	switch {
	case r == '٬':
		return false
	case 0xFF10 <= r && r <= 0xFF19:
		return true
	default:
		return unicode.IsNumber(r)
	}
}

// Cr is carriage return (\r, 13)
func Cr(r rune) bool {
	return r == '\r'
}

// Lf is line feed (\n, 10)
func Lf(r rune) bool {
	return r == '\n'
}

var addKatakana = rangetable.New(
	0x3031,
	0x3032,
	0x3033,
	0x3034,
	0x3035,
	0x309B,
	0x309C,
	0x30A0,
	0x30FC,
	0xFF70,
)

// Katakana is defined here: https://unicode.org/reports/tr29/#Katakana
func Katakana(r rune) bool {
	return unicode.Is(unicode.Katakana, r) || unicode.Is(addKatakana, r)
}

// HebrewLetter is defined here: https://unicode.org/reports/tr29/#Hebrew_Letter
func HebrewLetter(r rune) bool {
	return unicode.Is(unicode.Hebrew, r) && unicode.IsLetter(r)
}

var newLine = rangetable.New(
	0x000B,
	0x000C,
	0x0085,
	0x2028,
	0x2029,
)

// Newline is defined here: https://unicode.org/reports/tr29/#WB3a
func Newline(r rune) bool {
	return unicode.Is(newLine, r)
}

// SingleQuote is defined here: https://unicode.org/reports/tr29/#Single_Quote
func SingleQuote(r rune) bool {
	return r == '\''
}

// DoubleQuote is defined here: https://unicode.org/reports/tr29/#Double_Quote
func DoubleQuote(r rune) bool {
	return r == '"'
}

// WSegSpace is defined here: https://unicode.org/reports/tr29/#WSegSpace
func WSegSpace(r rune) bool {
	return unicode.Is(unicode.Zs, r)
}

// ExtendNumLet is defined here: https://unicode.org/reports/tr29/#ExtendNumLetWB
func ExtendNumLet(r rune) bool {
	return unicode.Is(unicode.Pc, r) || r == 0x202F
}
<|endoftext|>


<commit_before>package jason

import (
	"encoding/json"
	"errors"
	"io"
)

// Value represents an arbitrary JSON value.
// It may contain a bool, number, string, object, array or null.
type Value struct {
	data   interface{}
	exists bool // Used to separate nil and non-existing values
}

// Object represents an object JSON object.
// It inherets from Value but with an additional method to access
// a map representation of it's content. It's useful when iterating.
type Object struct {
	Value
	m     map[string]*Value
	valid bool
}

// Returns the golang map.
// Needed when iterating through the values of the object.
func (v *Object) Map() map[string]*Value {
	return v.m
}

// Creates a new value from an io.reader.
// Returns an error if the reader does not contain valid json.
// Useful for parsing the body of a net/http response.
// Example: NewFromReader(res.Body)
func NewValueFromReader(reader io.Reader) (*Value, error) {
	j := new(Value)
	d := json.NewDecoder(reader)
	err := d.Decode(&j.data)
	return j, err
}

// Creates a new value from bytes.
// Returns an error if the bytes are not valid json.
func NewValueFromBytes(b []byte) (*Value, error) {
	j := new(Value)
	err := json.Unmarshal(b, &j.data)
	return j, err
}

func objectFromValue(v *Value, err error) (*Object, error) {
	if err != nil {
		return nil, err
	} else {

		o, err := v.AsObject()

		if err != nil {
			return nil, err
		} else {
			return o, nil
		}

	}
}

func NewObjectFromBytes(b []byte) (*Object, error) {
	return objectFromValue(NewValueFromBytes(b))
}

func NewObjectFromReader(reader io.Reader) (*Object, error) {
	return objectFromValue(NewValueFromReader(reader))
}

// Marshal into bytes.
func (v *Value) Marshal() ([]byte, error) {
	return json.Marshal(v.data)
}

// Private Get
func (v *Value) get(key string) (*Value, error) {

	// Assume this is an object
	obj, err := v.AsObject()

	if err == nil {
		child, ok := obj.Map()[key]
		if ok {
			return child, nil
		} else {
			return nil, errors.New("key not found")
		}
	}

	return nil, err
}

// Private get path
func (v *Value) getPath(keys []string) (*Value, error) {
	current := v
	var err error
	for _, key := range keys {
		current, err = current.get(key)

		if err != nil {
			return nil, err
		}
	}
	return current, nil
}

// Gets the value at key path.
// Returns error if the value does not exist.
// Example: Get("address", "street")
func (v *Object) Get(keys ...string) (*Value, error) {
	return v.getPath(keys)
}

// Gets the value at key path and attempts to typecast the value into an object.
// Returns error if the value is not a json object.
func (v *Object) GetObject(keys ...string) (*Object, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		obj, err := child.AsObject()

		if err != nil {
			return nil, err
		} else {
			return obj, nil
		}

	}

	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into a string.
// Returns error if the value is not a json string.
func (v *Object) GetString(keys ...string) (string, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return "", err
	} else {
		return child.AsString()
	}

	return "", nil
}

// Gets the value at key path and attempts to typecast the value into null.
// Returns error if the value is not json null.
func (v *Object) GetNull(keys ...string) error {
	child, err := v.getPath(keys)

	if err != nil {
		return err
	}

	return child.AsNull()
}

// Gets the value at key path and attempts to typecast the value into a float64.
// Returns error if the value is not a json number.
func (v *Object) GetNumber(keys ...string) (float64, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return 0, err
	} else {

		n, err := child.AsNumber()

		if err != nil {
			return 0, err
		} else {
			return n, nil
		}
	}

	return 0, nil
}

// Gets the value at key path and attempts to typecast the value into a bool.
// Returns error if the value is not a json boolean.
func (v *Object) GetBoolean(keys ...string) (bool, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return false, err
	}

	return child.AsBoolean()
}

// Gets the value at key path and attempts to typecast the value into an array.
// Returns error if the value is not a json array.
func (v *Object) GetArray(keys ...string) ([]*Value, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		return child.AsArray()

	}

	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of objects.
// Returns error if the value is not a json array or if any of the contained objects are not objects.
func (v *Object) GetObjectArray(keys ...string) ([]*Object, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]*Object, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsObject()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}

	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of string.
// Returns error if the value is not a json array or if any of the contained objects are not strings.
func (v *Object) GetStringArray(keys ...string) ([]string, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]string, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsString()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}
	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of floats.
// Returns error if the value is not a json array or if any of the contained objects are not numbers.
func (v *Object) GetNumberArray(keys ...string) ([]float64, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]float64, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsNumber()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}
	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of bools.
// Returns error if the value is not a json array or if any of the contained objects are not booleans.
func (v *Object) GetBooleanArray(keys ...string) ([]bool, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]bool, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsBoolean()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}
	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of nulls.
// Returns length, or an error if the value is not a json array or if any of the contained objects are not nulls.
func (v *Object) GetNullArray(keys ...string) (int64, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return 0, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return 0, err
		} else {

			var length int64 = 0

			for _, arrayItem := range array {
				err := arrayItem.AsNull()

				if err != nil {
					return 0, err
				} else {
					length++
				}

			}
			return length, nil
		}
	}

	return 0, nil
}

// Returns an error if the value is not actually null
func (v *Value) AsNull() error {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case nil:
		valid = v.exists // Valid only if j also exists, since other values could possibly also be nil
		break
	}

	if valid {
		return nil
	}

	return errors.New("is not null")

}

// Attempts to typecast the current value into an array.
// Returns error if the current value is not a json array.
func (v *Value) AsArray() ([]*Value, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case []interface{}:
		valid = true
		break
	}

	// Unsure if this is a good way to use slices, it's probably not
	var slice []*Value

	if valid {

		for _, element := range v.data.([]interface{}) {
			child := Value{element, true}
			slice = append(slice, &child)
		}

		return slice, nil
	}

	return slice, errors.New("Not an array")

}

// Attempts to typecast the current value into a float64.
// Returns error if the current value is not a json number.
func (v *Value) AsNumber() (float64, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case float64:
		valid = true
		break
	}

	if valid {
		return v.data.(float64), nil
	}

	return 0, errors.New("not a number")
}

// Attempts to typecast the current value into a bool.
// Returns error if the current value is not a json boolean.
func (v *Value) AsBoolean() (bool, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case bool:
		valid = true
		break
	}

	if valid {
		return v.data.(bool), nil
	}

	return false, errors.New("no bool")
}

// Attempts to typecast the current value into an object.
// Returns error if the current value is not a json object.
func (v *Value) AsObject() (*Object, error) {

	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case map[string]interface{}:
		valid = true
		break
	}

	if valid {
		obj := new(Object)
		obj.valid = valid

		m := make(map[string]*Value)

		if valid {

			for key, element := range v.data.(map[string]interface{}) {
				m[key] = &Value{element, true}

			}
		}

		obj.data = v.data
		obj.m = m

		return obj, nil
	}

	return nil, errors.New("not an object")
}

// Attempts to typecast the current value into a string.
// Returns error if the current value is not a json string
func (v *Value) AsString() (string, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case string:
		valid = true
		break
	}

	if valid {
		return v.data.(string), nil
	}

	return "", errors.New("not a string")
}

// Returns the value a json formatted string.
// Note: The method named String() is used by golang's log method for logging.
func (v *Value) String() string {
	f, err := json.Marshal(v.data)
	if err != nil {
		return err.Error()
	} else {
		return string(f)
	}
}
<commit_msg>Remove unnecessary else-statements.<commit_after>package jason

import (
	"encoding/json"
	"errors"
	"io"
)

// Value represents an arbitrary JSON value.
// It may contain a bool, number, string, object, array or null.
type Value struct {
	data   interface{}
	exists bool // Used to separate nil and non-existing values
}

// Object represents an object JSON object.
// It inherets from Value but with an additional method to access
// a map representation of it's content. It's useful when iterating.
type Object struct {
	Value
	m     map[string]*Value
	valid bool
}

// Returns the golang map.
// Needed when iterating through the values of the object.
func (v *Object) Map() map[string]*Value {
	return v.m
}

// Creates a new value from an io.reader.
// Returns an error if the reader does not contain valid json.
// Useful for parsing the body of a net/http response.
// Example: NewFromReader(res.Body)
func NewValueFromReader(reader io.Reader) (*Value, error) {
	j := new(Value)
	d := json.NewDecoder(reader)
	err := d.Decode(&j.data)
	return j, err
}

// Creates a new value from bytes.
// Returns an error if the bytes are not valid json.
func NewValueFromBytes(b []byte) (*Value, error) {
	j := new(Value)
	err := json.Unmarshal(b, &j.data)
	return j, err
}

func objectFromValue(v *Value, err error) (*Object, error) {
	if err != nil {
		return nil, err
	}

	o, err := v.AsObject()

	if err != nil {
		return nil, err
	}

	return o, nil
}

func NewObjectFromBytes(b []byte) (*Object, error) {
	return objectFromValue(NewValueFromBytes(b))
}

func NewObjectFromReader(reader io.Reader) (*Object, error) {
	return objectFromValue(NewValueFromReader(reader))
}

// Marshal into bytes.
func (v *Value) Marshal() ([]byte, error) {
	return json.Marshal(v.data)
}

// Private Get
func (v *Value) get(key string) (*Value, error) {

	// Assume this is an object
	obj, err := v.AsObject()

	if err == nil {
		child, ok := obj.Map()[key]
		if ok {
			return child, nil
		} else {
			return nil, errors.New("key not found")
		}
	}

	return nil, err
}

// Private get path
func (v *Value) getPath(keys []string) (*Value, error) {
	current := v
	var err error
	for _, key := range keys {
		current, err = current.get(key)

		if err != nil {
			return nil, err
		}
	}
	return current, nil
}

// Gets the value at key path.
// Returns error if the value does not exist.
// Example: Get("address", "street")
func (v *Object) Get(keys ...string) (*Value, error) {
	return v.getPath(keys)
}

// Gets the value at key path and attempts to typecast the value into an object.
// Returns error if the value is not a json object.
func (v *Object) GetObject(keys ...string) (*Object, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		obj, err := child.AsObject()

		if err != nil {
			return nil, err
		} else {
			return obj, nil
		}

	}

	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into a string.
// Returns error if the value is not a json string.
func (v *Object) GetString(keys ...string) (string, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return "", err
	} else {
		return child.AsString()
	}

	return "", nil
}

// Gets the value at key path and attempts to typecast the value into null.
// Returns error if the value is not json null.
func (v *Object) GetNull(keys ...string) error {
	child, err := v.getPath(keys)

	if err != nil {
		return err
	}

	return child.AsNull()
}

// Gets the value at key path and attempts to typecast the value into a float64.
// Returns error if the value is not a json number.
func (v *Object) GetNumber(keys ...string) (float64, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return 0, err
	} else {

		n, err := child.AsNumber()

		if err != nil {
			return 0, err
		} else {
			return n, nil
		}
	}

	return 0, nil
}

// Gets the value at key path and attempts to typecast the value into a bool.
// Returns error if the value is not a json boolean.
func (v *Object) GetBoolean(keys ...string) (bool, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return false, err
	}

	return child.AsBoolean()
}

// Gets the value at key path and attempts to typecast the value into an array.
// Returns error if the value is not a json array.
func (v *Object) GetArray(keys ...string) ([]*Value, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		return child.AsArray()

	}

	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of objects.
// Returns error if the value is not a json array or if any of the contained objects are not objects.
func (v *Object) GetObjectArray(keys ...string) ([]*Object, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]*Object, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsObject()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}

	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of string.
// Returns error if the value is not a json array or if any of the contained objects are not strings.
func (v *Object) GetStringArray(keys ...string) ([]string, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]string, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsString()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}
	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of floats.
// Returns error if the value is not a json array or if any of the contained objects are not numbers.
func (v *Object) GetNumberArray(keys ...string) ([]float64, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]float64, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsNumber()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}
	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of bools.
// Returns error if the value is not a json array or if any of the contained objects are not booleans.
func (v *Object) GetBooleanArray(keys ...string) ([]bool, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return nil, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return nil, err
		} else {

			typedArray := make([]bool, len(array))

			for index, arrayItem := range array {
				typedArrayItem, err := arrayItem.AsBoolean()

				if err != nil {
					return nil, err
				} else {
					typedArray[index] = typedArrayItem
				}

			}
			return typedArray, nil
		}
	}
	return nil, nil
}

// Gets the value at key path and attempts to typecast the value into an array of nulls.
// Returns length, or an error if the value is not a json array or if any of the contained objects are not nulls.
func (v *Object) GetNullArray(keys ...string) (int64, error) {
	child, err := v.getPath(keys)

	if err != nil {
		return 0, err
	} else {

		array, err := child.AsArray()

		if err != nil {
			return 0, err
		} else {

			var length int64 = 0

			for _, arrayItem := range array {
				err := arrayItem.AsNull()

				if err != nil {
					return 0, err
				} else {
					length++
				}

			}
			return length, nil
		}
	}

	return 0, nil
}

// Returns an error if the value is not actually null
func (v *Value) AsNull() error {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case nil:
		valid = v.exists // Valid only if j also exists, since other values could possibly also be nil
		break
	}

	if valid {
		return nil
	}

	return errors.New("is not null")

}

// Attempts to typecast the current value into an array.
// Returns error if the current value is not a json array.
func (v *Value) AsArray() ([]*Value, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case []interface{}:
		valid = true
		break
	}

	// Unsure if this is a good way to use slices, it's probably not
	var slice []*Value

	if valid {

		for _, element := range v.data.([]interface{}) {
			child := Value{element, true}
			slice = append(slice, &child)
		}

		return slice, nil
	}

	return slice, errors.New("Not an array")

}

// Attempts to typecast the current value into a float64.
// Returns error if the current value is not a json number.
func (v *Value) AsNumber() (float64, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case float64:
		valid = true
		break
	}

	if valid {
		return v.data.(float64), nil
	}

	return 0, errors.New("not a number")
}

// Attempts to typecast the current value into a bool.
// Returns error if the current value is not a json boolean.
func (v *Value) AsBoolean() (bool, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case bool:
		valid = true
		break
	}

	if valid {
		return v.data.(bool), nil
	}

	return false, errors.New("no bool")
}

// Attempts to typecast the current value into an object.
// Returns error if the current value is not a json object.
func (v *Value) AsObject() (*Object, error) {

	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case map[string]interface{}:
		valid = true
		break
	}

	if valid {
		obj := new(Object)
		obj.valid = valid

		m := make(map[string]*Value)

		if valid {

			for key, element := range v.data.(map[string]interface{}) {
				m[key] = &Value{element, true}

			}
		}

		obj.data = v.data
		obj.m = m

		return obj, nil
	}

	return nil, errors.New("not an object")
}

// Attempts to typecast the current value into a string.
// Returns error if the current value is not a json string
func (v *Value) AsString() (string, error) {
	var valid bool

	// Check the type of this data
	switch v.data.(type) {
	case string:
		valid = true
		break
	}

	if valid {
		return v.data.(string), nil
	}

	return "", errors.New("not a string")
}

// Returns the value a json formatted string.
// Note: The method named String() is used by golang's log method for logging.
func (v *Value) String() string {
	f, err := json.Marshal(v.data)
	if err != nil {
		return err.Error()
	}

	return string(f)
}
<|endoftext|>