<commit_before>/*
 * Copyright 2014 Jason Woods.
 *
 * 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 transports

import (
  "testing"
)

func TestAddressPoolIP(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"127.0.0.1:1234"})

  addr, desc, err := pool.Next()

  // Should have succeeeded
  if err != nil {
    t.Error("Address pool did not parse IP correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  } else if desc != "127.0.0.1:1234" {
    t.Error("Address pool did not return correct desc: ", desc)
  } else if addr.String() != "127.0.0.1:1234" {
    t.Error("Address pool did not return correct addr: ", addr.String())
  }
}

func TestAddressPoolHost(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"google-public-dns-a.google.com:555"})

  addr, desc, err := pool.Next()

  if err != nil {
    t.Error("Address pool did not parse Host correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  } else if desc != "8.8.8.8:555 (google-public-dns-a.google.com)" && desc != "[2001:4860:4860::8888]:555 (google-public-dns-a.google.com)" {
    t.Error("Address pool did not return correct desc: ", desc)
  } else if addr.String() != "8.8.8.8:555" && addr.String() != "[2001:4860:4860::8888]:555" {
    t.Error("Address pool did not return correct addr: ", addr.String())
  }
}

func TestAddressPoolHostMultiple(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"google.com:555"})

  for i := 0; i < 2; i++ {
    addr, _, err := pool.Next()

    // Should have succeeeded
    if err != nil {
      t.Error("Address pool did not parse Host correctly: ", err)
    } else if addr == nil {
      t.Error("Address pool did not returned nil addr")
    }

    if i == 0 {
      if pool.IsLast() {
        t.Error("Address pool did not return multiple addresses")
      }
    }
  }
}

func TestAddressPoolSrv(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"@_xmpp-server._tcp.google.com"})

  addr, _, err := pool.Next()

  // Should have succeeeded
  if err != nil {
    t.Error("Address pool did not parse SRV correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  }
}

func TestAddressPoolSrvRfc(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"@google.com"})
  pool.SetRfc2782(true, "xmpp-server")

  addr, _, err := pool.Next()

  // Should have succeeeded
  if err != nil {
    t.Error("Address pool did not parse RFC SRV correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  }
}

func TestAddressPoolInvalid(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"127.0..0:1234"})

  _, _, err := pool.Next()

  // Should have failed
  if err == nil {
    t.Logf("Address pool did not return failure correctly")
    t.FailNow()
  }
}

func TestAddressPoolHostFailure(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"google-public-dns-not-exist.google.com:1234"})

  _, _, err := pool.Next()

  // Should have failed
  if err == nil {
    t.Logf("Address pool did not return failure correctly")
    t.FailNow()
  }
}

func TestAddressPoolIsLast(t *testing.T) {
  // Test that IsLastServer works correctly
  pool := NewAddressPool([]string{"google.com:1234"})

  // Should report as last
  if !pool.IsLast() {
    t.Error("Address pool IsLast did not return correctly")
  }

  for i := 0; i <= 42; i++ {
    _, _, err := pool.Next()

    // Should succeed
    if err != nil {
      t.Error("Address pool did not parse Host correctly")
    }

    if i <= 1 {
      // Should not report as last
      if pool.IsLast() {
        t.Error("Address pool IsLast did not return correctly")
      }

      continue
    }

    // Wait until last
    if pool.IsLast() {
      return
    }
  }

  // Hit 42 servers without hitting last
  t.Error("Address pool IsLast did not return correctly")
}

func TestAddressPoolIsLastServer(t *testing.T) {
  // Test that IsLastServer works correctly
  pool := NewAddressPool([]string{"127.0.0.1:1234", "127.0.0.1:1234", "127.0.0.1:1234"})

  // Should report as last server
  if !pool.IsLastServer() {
    t.Error("Address pool IsLastServer did not return correctly")
  }

  for i := 0; i < 3; i++ {
    _, _, err := pool.Next()

    // Should succeed
    if err != nil {
      t.Error("Address pool did not parse IP correctly")
    }

    if i < 2 {
      // Should not report as last server
      if pool.IsLastServer() {
        t.Error("Address pool IsLastServer did not return correctly")
      }

      continue
    }
  }

  // Should report as last server
  if !pool.IsLastServer() {
    t.Error("Address pool IsLastServer did not return correctly")
  }
}

func TestAddressPoolNextServer(t *testing.T) {
  // Test that IsLastServer works correctly
  pool := NewAddressPool([]string{"google.com:1234", "google.com:1234"})

  cnt := 0
  for i := 0; i < 42; i++ {
    addr, err := pool.NextServer()

    // Should succeed
    if err != nil {
      t.Error("Address pool did not parse IP correctly")
    } else if addr != "google.com:1234" {
      t.Error("Address pool returned incorrect address: ", addr)
    }

    cnt++

    // Break on last server
    if pool.IsLastServer() {
      break
    }
  }

  // Should have stopped at 2 servers
  if cnt != 2 {
    t.Error("Address pool NextServer failed")
  }
}
<commit_msg>Fix tests by switching to outlook.com for IsLast test<commit_after>/*
 * Copyright 2014 Jason Woods.
 *
 * 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 transports

import (
  "testing"
)

func TestAddressPoolIP(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"127.0.0.1:1234"})

  addr, desc, err := pool.Next()

  // Should have succeeeded
  if err != nil {
    t.Error("Address pool did not parse IP correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  } else if desc != "127.0.0.1:1234" {
    t.Error("Address pool did not return correct desc: ", desc)
  } else if addr.String() != "127.0.0.1:1234" {
    t.Error("Address pool did not return correct addr: ", addr.String())
  }
}

func TestAddressPoolHost(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"google-public-dns-a.google.com:555"})

  addr, desc, err := pool.Next()

  if err != nil {
    t.Error("Address pool did not parse Host correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  } else if desc != "8.8.8.8:555 (google-public-dns-a.google.com)" && desc != "[2001:4860:4860::8888]:555 (google-public-dns-a.google.com)" {
    t.Error("Address pool did not return correct desc: ", desc)
  } else if addr.String() != "8.8.8.8:555" && addr.String() != "[2001:4860:4860::8888]:555" {
    t.Error("Address pool did not return correct addr: ", addr.String())
  }
}

func TestAddressPoolHostMultiple(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"google.com:555"})

  for i := 0; i < 2; i++ {
    addr, _, err := pool.Next()

    // Should have succeeeded
    if err != nil {
      t.Error("Address pool did not parse Host correctly: ", err)
    } else if addr == nil {
      t.Error("Address pool did not returned nil addr")
    }

    if i == 0 {
      if pool.IsLast() {
        t.Error("Address pool did not return multiple addresses")
      }
    }
  }
}

func TestAddressPoolSrv(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"@_xmpp-server._tcp.google.com"})

  addr, _, err := pool.Next()

  // Should have succeeeded
  if err != nil {
    t.Error("Address pool did not parse SRV correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  }
}

func TestAddressPoolSrvRfc(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"@google.com"})
  pool.SetRfc2782(true, "xmpp-server")

  addr, _, err := pool.Next()

  // Should have succeeeded
  if err != nil {
    t.Error("Address pool did not parse RFC SRV correctly: ", err)
  } else if addr == nil {
    t.Error("Address pool did not returned nil addr")
  }
}

func TestAddressPoolInvalid(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"127.0..0:1234"})

  _, _, err := pool.Next()

  // Should have failed
  if err == nil {
    t.Logf("Address pool did not return failure correctly")
    t.FailNow()
  }
}

func TestAddressPoolHostFailure(t *testing.T) {
  // Test failures when parsing
  pool := NewAddressPool([]string{"google-public-dns-not-exist.google.com:1234"})

  _, _, err := pool.Next()

  // Should have failed
  if err == nil {
    t.Logf("Address pool did not return failure correctly")
    t.FailNow()
  }
}

func TestAddressPoolIsLast(t *testing.T) {
  // Test that IsLastServer works correctly
  pool := NewAddressPool([]string{"outlook.com:1234"})

  // Should report as last
  if !pool.IsLast() {
    t.Error("Address pool IsLast did not return correctly")
  }

  for i := 0; i <= 42; i++ {
    _, _, err := pool.Next()

    // Should succeed
    if err != nil {
      t.Error("Address pool did not parse Host correctly")
    }

    if i <= 1 {
      // Should not report as last
      if pool.IsLast() {
        t.Error("Address pool IsLast did not return correctly")
      }

      continue
    }

    // Wait until last
    if pool.IsLast() {
      return
    }
  }

  // Hit 42 servers without hitting last
  t.Error("Address pool IsLast did not return correctly")
}

func TestAddressPoolIsLastServer(t *testing.T) {
  // Test that IsLastServer works correctly
  pool := NewAddressPool([]string{"127.0.0.1:1234", "127.0.0.1:1234", "127.0.0.1:1234"})

  // Should report as last server
  if !pool.IsLastServer() {
    t.Error("Address pool IsLastServer did not return correctly")
  }

  for i := 0; i < 3; i++ {
    _, _, err := pool.Next()

    // Should succeed
    if err != nil {
      t.Error("Address pool did not parse IP correctly")
    }

    if i < 2 {
      // Should not report as last server
      if pool.IsLastServer() {
        t.Error("Address pool IsLastServer did not return correctly")
      }

      continue
    }
  }

  // Should report as last server
  if !pool.IsLastServer() {
    t.Error("Address pool IsLastServer did not return correctly")
  }
}

func TestAddressPoolNextServer(t *testing.T) {
  // Test that IsLastServer works correctly
  pool := NewAddressPool([]string{"google.com:1234", "google.com:1234"})

  cnt := 0
  for i := 0; i < 42; i++ {
    addr, err := pool.NextServer()

    // Should succeed
    if err != nil {
      t.Error("Address pool did not parse IP correctly")
    } else if addr != "google.com:1234" {
      t.Error("Address pool returned incorrect address: ", addr)
    }

    cnt++

    // Break on last server
    if pool.IsLastServer() {
      break
    }
  }

  // Should have stopped at 2 servers
  if cnt != 2 {
    t.Error("Address pool NextServer failed")
  }
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"fmt"
	"image"
	"image/png"

	"github.com/thinkofdeath/steven/resource"
)

var (
	grassBiomeColors   *image.NRGBA
	foliageBiomeColors *image.NRGBA
)

func init() {
	grassBiomeColors = loadBiomeColors("grass")
	foliageBiomeColors = loadBiomeColors("foliage")
}

func loadBiomeColors(name string) *image.NRGBA {
	f, _ := resource.Open("minecraft", fmt.Sprintf("textures/colormap/%s.png", name))
	defer f.Close()
	img, err := png.Decode(f)
	if err != nil {
		panic(err)
	}
	return img.(*image.NRGBA)
}
<commit_msg>steven: allow for all types of images for biome colors<commit_after>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"fmt"
	"image"
	icolor "image/color"
	"image/png"

	"github.com/thinkofdeath/steven/resource"
)

var (
	grassBiomeColors   *image.NRGBA
	foliageBiomeColors *image.NRGBA
)

func init() {
	grassBiomeColors = loadBiomeColors("grass")
	foliageBiomeColors = loadBiomeColors("foliage")
}

func loadBiomeColors(name string) *image.NRGBA {
	f, _ := resource.Open("minecraft", fmt.Sprintf("textures/colormap/%s.png", name))
	defer f.Close()
	img, err := png.Decode(f)
	if err != nil {
		panic(err)
	}
	i, ok := img.(*image.NRGBA)
	if !ok {
		i = convertImage(img)
	}
	return i
}

func convertImage(img image.Image) *image.NRGBA {
	width, height := img.Bounds().Dx(), img.Bounds().Dy()
	pix := make([]byte, width*height*4)
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			col := icolor.NRGBAModel.Convert(img.At(x, y)).(icolor.NRGBA)
			index := (y*width + x) * 4
			pix[index] = col.R
			pix[index+1] = col.G
			pix[index+2] = col.B
			pix[index+3] = col.A
		}
	}
	i := image.NewNRGBA(img.Bounds())
	i.Pix = pix
	return i
}
<|endoftext|>


<commit_before>package check

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

var (
	skipDirs     = []string{"Godeps", "vendor", "third_party"}
	skipSuffixes = []string{".pb.go", ".pb.gw.go"}
)

func AddSkipDirs(params []string) []string {
	for _, dir := range skipDirs {
		params = append(params, fmt.Sprintf("--skip=%s", dir))
	}
	return params
}

// GoFiles returns a slice of Go filenames
// in a given directory.
func GoFiles(dir string) ([]string, error) {
	var filenames []string
	visit := func(fp string, fi os.FileInfo, err error) error {
		for _, skip := range skipDirs {
			if strings.Contains(fp, skip) {
				return nil
			}
		}
		if err != nil {
			fmt.Println(err) // can't walk here,
			return nil       // but continue walking elsewhere
		}
		if fi.IsDir() {
			return nil // not a file.  ignore.
		}
		fiName := fi.Name()
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(fiName, skip) {
				return nil
			}
		}
		ext := filepath.Ext(fiName)
		if ext == ".go" {
			filenames = append(filenames, fp)
		}
		return nil
	}

	err := filepath.Walk(dir, visit)

	return filenames, err
}

// lineCount returns the number of lines in a given file
func lineCount(filepath string) (int, error) {
	out, err := exec.Command("wc", "-l", filepath).Output()
	if err != nil {
		return 0, err
	}
	// wc output is like: 999 filename.go
	count, err := strconv.Atoi(strings.Split(strings.TrimSpace(string(out)), " ")[0])
	if err != nil {
		return 0, err
	}

	return count, nil
}

// Error contains the line number and the reason for
// an error output from a command
type Error struct {
	LineNumber  int    `json:"line_number"`
	ErrorString string `json:"error_string"`
}

// FileSummary contains the filename, location of the file
// on GitHub, and all of the errors related to the file
type FileSummary struct {
	Filename string  `json:"filename"`
	FileURL  string  `json:"file_url"`
	Errors   []Error `json:"errors"`
}

// ByFilename implements sort.Interface for []Person based on
// the Age field.
type ByFilename []FileSummary

func (a ByFilename) Len() int           { return len(a) }
func (a ByFilename) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByFilename) Less(i, j int) bool { return a[i].Filename < a[j].Filename }

func (fs *FileSummary) AddError(out string) error {
	s := strings.SplitN(out, ":", 2)
	msg := strings.SplitAfterN(s[1], ":", 3)[2]

	e := Error{ErrorString: msg}
	ls := strings.Split(s[1], ":")
	ln, err := strconv.Atoi(ls[0])
	if err != nil {
		return err
	}
	e.LineNumber = ln

	fs.Errors = append(fs.Errors, e)

	return nil
}

// GoTool runs a given go command (for example gofmt, go tool vet)
// on a directory
func GoTool(dir string, filenames, command []string) (float64, []FileSummary, error) {
	var failed = []FileSummary{}
	params := command[1:]
	params = append(params, dir+"/...")

	cmd := exec.Command(command[0], params...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	out := bufio.NewScanner(stdout)

	githubLink := strings.TrimPrefix(dir, "repos/src")

	var fs FileSummary
	var filename string
	for out.Scan() {
		name := strings.Split(out.Text(), ":")[0]
		name = strings.TrimPrefix(name, "repos/src")
		if name != filename {
			if fs.Filename != "" {
				failed = append(failed, fs)
			}
			filename = name
			fileURL := "https://" + strings.TrimPrefix(dir, "repos/src/") + "/blob/master" + strings.TrimPrefix(filename, githubLink)
			fs = FileSummary{
				Filename: filename,
				FileURL:  fileURL,
			}
		}
		err = fs.AddError(out.Text())
		if err != nil {
			return 0, []FileSummary{}, err
		}
	}
	if err := out.Err(); err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Wait()
	if exitErr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0

		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			// some commands exit 1 when files fail to pass (for example go vet)
			if status.ExitStatus() != 1 {
				return 0, failed, err
				// return 0, Error{}, err
			}
		}
	}

	if len(filenames) == 1 {
		lc, err := lineCount(filenames[0])
		if err != nil {
			return 0, failed, err
		}

		var errors int
		if len(failed) != 0 {
			errors = len(failed[0].Errors)
		}

		return float64(lc-errors) / float64(lc), failed, nil
	}

	return float64(len(filenames)-len(failed)) / float64(len(filenames)), failed, nil
}
<commit_msg>keep a map of filename => FileSummary since lines can appear out of order<commit_after>package check

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

var (
	skipDirs     = []string{"Godeps", "vendor", "third_party"}
	skipSuffixes = []string{".pb.go", ".pb.gw.go"}
)

func AddSkipDirs(params []string) []string {
	for _, dir := range skipDirs {
		params = append(params, fmt.Sprintf("--skip=%s", dir))
	}
	return params
}

// GoFiles returns a slice of Go filenames
// in a given directory.
func GoFiles(dir string) ([]string, error) {
	var filenames []string
	visit := func(fp string, fi os.FileInfo, err error) error {
		for _, skip := range skipDirs {
			if strings.Contains(fp, skip) {
				return nil
			}
		}
		if err != nil {
			fmt.Println(err) // can't walk here,
			return nil       // but continue walking elsewhere
		}
		if fi.IsDir() {
			return nil // not a file.  ignore.
		}
		fiName := fi.Name()
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(fiName, skip) {
				return nil
			}
		}
		ext := filepath.Ext(fiName)
		if ext == ".go" {
			filenames = append(filenames, fp)
		}
		return nil
	}

	err := filepath.Walk(dir, visit)

	return filenames, err
}

// lineCount returns the number of lines in a given file
func lineCount(filepath string) (int, error) {
	out, err := exec.Command("wc", "-l", filepath).Output()
	if err != nil {
		return 0, err
	}
	// wc output is like: 999 filename.go
	count, err := strconv.Atoi(strings.Split(strings.TrimSpace(string(out)), " ")[0])
	if err != nil {
		return 0, err
	}

	return count, nil
}

// Error contains the line number and the reason for
// an error output from a command
type Error struct {
	LineNumber  int    `json:"line_number"`
	ErrorString string `json:"error_string"`
}

// FileSummary contains the filename, location of the file
// on GitHub, and all of the errors related to the file
type FileSummary struct {
	Filename string  `json:"filename"`
	FileURL  string  `json:"file_url"`
	Errors   []Error `json:"errors"`
}

// ByFilename implements sort.Interface for []Person based on
// the Age field.
type ByFilename []FileSummary

func (a ByFilename) Len() int           { return len(a) }
func (a ByFilename) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByFilename) Less(i, j int) bool { return a[i].Filename < a[j].Filename }

func (fs *FileSummary) AddError(out string) error {
	s := strings.SplitN(out, ":", 2)
	msg := strings.SplitAfterN(s[1], ":", 3)[2]

	e := Error{ErrorString: msg}
	ls := strings.Split(s[1], ":")
	ln, err := strconv.Atoi(ls[0])
	if err != nil {
		return err
	}
	e.LineNumber = ln

	fs.Errors = append(fs.Errors, e)

	return nil
}

// GoTool runs a given go command (for example gofmt, go tool vet)
// on a directory
func GoTool(dir string, filenames, command []string) (float64, []FileSummary, error) {
	params := command[1:]
	params = append(params, dir+"/...")

	cmd := exec.Command(command[0], params...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	out := bufio.NewScanner(stdout)

	githubLink := strings.TrimPrefix(dir, "repos/src")

	// the same file can appear multiple times out of order
	// in the output, so we can't go line by line, have to store
	// a map of filename to FileSummary
	fsMap := map[string]FileSummary{}
	var failed = []FileSummary{}
	for out.Scan() {
		filename := strings.Split(out.Text(), ":")[0]
		filename = strings.TrimPrefix(filename, "repos/src")
		fileURL := "https://" + strings.TrimPrefix(dir, "repos/src/") + "/blob/master" + strings.TrimPrefix(filename, githubLink)
		fs := fsMap[filename]
		if fs.Filename == "" {
			fs.Filename = filename
			fs.FileURL = fileURL
		}
		err = fs.AddError(out.Text())
		if err != nil {
			return 0, []FileSummary{}, err
		}
		fsMap[filename] = fs
	}
	if err := out.Err(); err != nil {
		return 0, []FileSummary{}, err
	}

	for _, v := range fsMap {
		failed = append(failed, v)
	}

	err = cmd.Wait()
	if exitErr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0

		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			// some commands exit 1 when files fail to pass (for example go vet)
			if status.ExitStatus() != 1 {
				return 0, failed, err
				// return 0, Error{}, err
			}
		}
	}

	if len(filenames) == 1 {
		lc, err := lineCount(filenames[0])
		if err != nil {
			return 0, failed, err
		}

		var errors int
		if len(failed) != 0 {
			errors = len(failed[0].Errors)
		}

		return float64(lc-errors) / float64(lc), failed, nil
	}

	return float64(len(filenames)-len(failed)) / float64(len(filenames)), failed, nil
}
<|endoftext|>


<commit_before>package spvwallet

import (
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
	"time"
)

type Checkpoint struct {
	Height uint32
	Header wire.BlockHeader
}

var mainnetCheckpoints []Checkpoint
var testnet3Checkpoints []Checkpoint
var regtestCheckpoint Checkpoint

var BitcoinCashMainnetForkBlock *chainhash.Hash
var BitcoinCashTestnet3ForkBlock *chainhash.Hash

func init() {
	// Bitcoin Cash Fork
	BitcoinCashMainnetForkBlock, _ = chainhash.NewHashFromStr("000000000000000000651ef99cb9fcbe0dadde1d424bd9f15ff20136191a5eec")

	// Mainnet
	mainnetPrev, _ := chainhash.NewHashFromStr("0000000000000000010e0373719b7538e713e47d8d7189826dce4264d85a79b8")
	mainnetMerk, _ := chainhash.NewHashFromStr("28e3ae14925aeead5b44a885bca88e06ec37483ae905e65d57aa8cd60cb74b2f")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 477792,
		Header: wire.BlockHeader{
			Version:    536870914,
			PrevBlock:  *mainnetPrev,
			MerkleRoot: *mainnetMerk,
			Timestamp:  time.Unix(1501153434, 0),
			Bits:       402736949,
			Nonce:      165193412,
		},
	})
	if mainnetCheckpoints[0].Header.BlockHash().String() != "00000000000000000016ba7786309176445b838b36a16bd1ef3c3e3020473206" {
		panic("Invalid checkpoint")
	}

	// Testnet3
	BitcoinCashTestnet3ForkBlock, _ = chainhash.NewHashFromStr("00000000f17c850672894b9a75b63a1e72830bbd5f4c8889b5c1a80e7faef138")

	testnet3Prev, _ := chainhash.NewHashFromStr("0000000000001e8cdb2d98471a5c60bdbddbe644b9ad08e17a97b3a7dce1e332")
	testnet3Merk, _ := chainhash.NewHashFromStr("f675c565b293be2ad808b01b0a763557c8874e4aefe7f2eea0dab91b1f60ec45")
	testnet3Checkpoints = append(testnet3Checkpoints, Checkpoint{
		Height: 1151136,
		Header: wire.BlockHeader{
			Version:    536870912,
			PrevBlock:  *testnet3Prev,
			MerkleRoot: *testnet3Merk,
			Timestamp:  time.Unix(1498950206, 0),
			Bits:       436724869,
			Nonce:      2247874206,
		},
	})
	if testnet3Checkpoints[0].Header.BlockHash().String() != "00000000000002c04de174cf25c993b4dd221eb087c0601a599ff1977e230c99" {
		panic("Invalid checkpoint")
	}

	// Regtest
	regtestCheckpoint = Checkpoint{0, chaincfg.RegressionNetParams.GenesisBlock.Header}
}

func GetCheckpoint(walletCreationDate time.Time, params *chaincfg.Params) Checkpoint {
	switch params.Name {
	case chaincfg.MainNetParams.Name:
		for i := len(mainnetCheckpoints) - 1; i >= 0; i-- {
			if walletCreationDate.After(mainnetCheckpoints[i].Header.Timestamp) {
				return mainnetCheckpoints[i]
			}
		}
		return mainnetCheckpoints[0]
	case chaincfg.TestNet3Params.Name:
		for i := len(testnet3Checkpoints) - 1; i >= 0; i-- {
			if walletCreationDate.After(testnet3Checkpoints[i].Header.Timestamp) {
				return testnet3Checkpoints[i]
			}
		}
		return testnet3Checkpoints[0]

	default:
		return regtestCheckpoint
	}
}

func ForkHeight(params *chaincfg.Params) uint32 {
	switch params.Name {
	case chaincfg.MainNetParams.Name:
		return 478559
	case chaincfg.TestNet3Params.Name:
		return 1155875
	}
	return 0
}

func IsForkBlock(params *chaincfg.Params, header wire.BlockHeader) bool {
	ckHash := header.BlockHash()
	switch params.Name {
	case chaincfg.MainNetParams.Name:
		return ckHash.IsEqual(BitcoinCashMainnetForkBlock)
	case chaincfg.TestNet3Params.Name:
		return ckHash.IsEqual(BitcoinCashTestnet3ForkBlock)
	}
	return false
}
<commit_msg>Add additional mainnet checkpoints<commit_after>package spvwallet

import (
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
	"time"
)

type Checkpoint struct {
	Height uint32
	Header wire.BlockHeader
}

var mainnetCheckpoints []Checkpoint
var testnet3Checkpoints []Checkpoint
var regtestCheckpoint Checkpoint

var BitcoinCashMainnetForkBlock *chainhash.Hash
var BitcoinCashTestnet3ForkBlock *chainhash.Hash

func init() {
	// Bitcoin Cash Fork
	BitcoinCashMainnetForkBlock, _ = chainhash.NewHashFromStr("000000000000000000651ef99cb9fcbe0dadde1d424bd9f15ff20136191a5eec")

	// Mainnet
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 0,
		Header: chaincfg.MainNetParams.GenesisBlock.Header,
	})

	mainnetPrev1, _ := chainhash.NewHashFromStr("00000000103226f85fe2b68795f087dcec345e523363f18017e60b5c94175355")
	mainnetMerk1, _ := chainhash.NewHashFromStr("f90471766508bfe36158b4f2a5209dc5609d496f01b2d9b8f8fef1869fd8d382")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 48384,
		Header: wire.BlockHeader{
			Version:    1,
			PrevBlock:  *mainnetPrev1,
			MerkleRoot: *mainnetMerk1,
			Timestamp:  time.Unix(1270120042, 0),
			Bits:       472518933,
			Nonce:      317008837,
		},
	})
	if mainnetCheckpoints[1].Header.BlockHash().String() != "000000000f8bad9641203f9d788e72d55ff164f1a62a3e230df6f411f7d7d8fc" {
		panic("Invalid checkpoint 1")
	}

	mainnetPrev2, _ := chainhash.NewHashFromStr("00000000000292b850b8f8578e6b4d03cbb4a78ada44afbb4d2f80a16490e8f9")
	mainnetMerk2, _ := chainhash.NewHashFromStr("d1b77218087bf1c892d76ac0a6591e411322fb3399ee52a47b300158c61a6993")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 98784,
		Header: wire.BlockHeader{
			Version:    1,
			PrevBlock:  *mainnetPrev2,
			MerkleRoot: *mainnetMerk2,
			Timestamp:  time.Unix(1292956443, 0),
			Bits:       453281356,
			Nonce:      553309409,
		},
	})
	if mainnetCheckpoints[2].Header.BlockHash().String() != "0000000000043c4b0ed186109c36ce09e9af29b8ed0fdebcb909fa338877743d" {
		panic("Invalid checkpoint 2")
	}

	mainnetPrev3, _ := chainhash.NewHashFromStr("00000000000001b0d8d885e4d77d7c51e8f1fdaba68f229ac04d191915845f09")
	mainnetMerk3, _ := chainhash.NewHashFromStr("6664abb20174f8efcc8ae76b85c571919f6376c9083600d5e3fce7b94a985b12")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 149184,
		Header: wire.BlockHeader{
			Version:    1,
			PrevBlock:  *mainnetPrev3,
			MerkleRoot: *mainnetMerk3,
			Timestamp:  time.Unix(1318556675, 0),
			Bits:       436956491,
			Nonce:      1274332420,
		},
	})
	if mainnetCheckpoints[3].Header.BlockHash().String() != "000000000000028c550f87b05cddb1f4d461451bb26f0706f1ed5b20e3889fb9" {
		panic("Invalid checkpoint 3")
	}

	mainnetPrev4, _ := chainhash.NewHashFromStr("0000000000000304760bf583f4ac241c5ffe77312fa213634eba252c720530f1")
	mainnetMerk4, _ := chainhash.NewHashFromStr("4d91953d90f8ca7a60c40ec4f40a6bcd3832e3a6a079297352777d998371793c")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 199584,
		Header: wire.BlockHeader{
			Version:    1,
			PrevBlock:  *mainnetPrev4,
			MerkleRoot: *mainnetMerk4,
			Timestamp:  time.Unix(1348092851, 0),
			Bits:       436591499,
			Nonce:      887613184,
		},
	})
	if mainnetCheckpoints[4].Header.BlockHash().String() != "000000000000002e00a243fe9aa49c78f573091d17372c2ae0ae5e0f24f55b52" {
		panic("Invalid checkpoint 4")
	}

	mainnetPrev5, _ := chainhash.NewHashFromStr("0000000000000055e146e473b49fe656a1f2f4b8c33e72b80acc18f84d9fcc26")
	mainnetMerk5, _ := chainhash.NewHashFromStr("3e21fe7f80ac41dbcbdeb4f13fe9a0d78157625ba7c0d797d39918a5929bbf51")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 249984,
		Header: wire.BlockHeader{
			Version:    2,
			PrevBlock:  *mainnetPrev5,
			MerkleRoot: *mainnetMerk5,
			Timestamp:  time.Unix(1375527115, 0),
			Bits:       426957810,
			Nonce:      3431028336,
		},
	})
	if mainnetCheckpoints[5].Header.BlockHash().String() != "000000000000006f68295a01c059e45c38fe3ff5095107f067c52ae6437c3d4b" {
		panic("Invalid checkpoint 5")
	}

	mainnetPrev6, _ := chainhash.NewHashFromStr("000000000000000098686ab04cc22fec77e4fa2d76d5a3cc0eb8cbf4ed800cdc")
	mainnetMerk6, _ := chainhash.NewHashFromStr("e9087641b6f19e49dc37be1d35ec5b670b1baa4529883602b59068e1799adb44")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 298368,
		Header: wire.BlockHeader{
			Version:    2,
			PrevBlock:  *mainnetPrev6,
			MerkleRoot: *mainnetMerk6,
			Timestamp:  time.Unix(1398811175, 0),
			Bits:       419465580,
			Nonce:      952935459,
		},
	})
	if mainnetCheckpoints[6].Header.BlockHash().String() != "0000000000000000092dbe12467f95d456d9bd7ff12b88dc3bcdd28b4a7aa159" {
		panic("Invalid checkpoint 6")
	}

	mainnetPrev7, _ := chainhash.NewHashFromStr("00000000000000000b3ec9df7aebc319bb12491ba651337f9b3541e78446eca8")
	mainnetMerk7, _ := chainhash.NewHashFromStr("9bd3929bd9b575d103c43e5dc131f2956f1a8925f4f2596e603bd5f64deabbdf")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 348768,
		Header: wire.BlockHeader{
			Version:    2,
			PrevBlock:  *mainnetPrev7,
			MerkleRoot: *mainnetMerk7,
			Timestamp:  time.Unix(1427068411, 0),
			Bits:       404195570,
			Nonce:      903044756,
		},
	})
	if mainnetCheckpoints[7].Header.BlockHash().String() != "0000000000000000145865530e632fdcc732e2309645d759d738c7c9f4edb503" {
		panic("Invalid checkpoint 7")
	}

	mainnetPrev8, _ := chainhash.NewHashFromStr("0000000000000000074f9edbfc07648dc74392ba8248f0983ffea63431b3bc20")
	mainnetMerk8, _ := chainhash.NewHashFromStr("0ed1b9a40f94aec95e2843369bdcabaa42f860c82391c54874a7c193d7268eaa")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 399168,
		Header: wire.BlockHeader{
			Version:    4,
			PrevBlock:  *mainnetPrev8,
			MerkleRoot: *mainnetMerk8,
			Timestamp:  time.Unix(1455885256, 0),
			Bits:       403093919,
			Nonce:      3889666804,
		},
	})
	if mainnetCheckpoints[8].Header.BlockHash().String() != "000000000000000002ee8708b6c5ca0b4e055fbeed16189af256ed8a8d4b181d" {
		panic("Invalid checkpoint 8")
	}

	mainnetPrev9, _ := chainhash.NewHashFromStr("0000000000000000009f989a246ac4221ebdced8ccebae9b8d5c83b69bb5e7c8")
	mainnetMerk9, _ := chainhash.NewHashFromStr("97c6781a64bb3967f556263437252dba5baae9d46c3d0d6b6ab8073d6db4fff5")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 455616,
		Header: wire.BlockHeader{
			Version:    536870914,
			PrevBlock:  *mainnetPrev9,
			MerkleRoot: *mainnetMerk9,
			Timestamp:  time.Unix(1488567886, 0),
			Bits:       402809567,
			Nonce:      27288148,
		},
	})
	if mainnetCheckpoints[9].Header.BlockHash().String() != "000000000000000001f87b34342c67eadb07a5c48a6127ba1628dd43c0b97b45" {
		panic("Invalid checkpoint 9")
	}

	mainnetPrev10, _ := chainhash.NewHashFromStr("0000000000000000010e0373719b7538e713e47d8d7189826dce4264d85a79b8")
	mainnetMerk10, _ := chainhash.NewHashFromStr("28e3ae14925aeead5b44a885bca88e06ec37483ae905e65d57aa8cd60cb74b2f")
	mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
		Height: 477792,
		Header: wire.BlockHeader{
			Version:    536870914,
			PrevBlock:  *mainnetPrev10,
			MerkleRoot: *mainnetMerk10,
			Timestamp:  time.Unix(1501153434, 0),
			Bits:       402736949,
			Nonce:      165193412,
		},
	})
	if mainnetCheckpoints[10].Header.BlockHash().String() != "00000000000000000016ba7786309176445b838b36a16bd1ef3c3e3020473206" {
		panic("Invalid checkpoint 10")
	}

	// Testnet3
	BitcoinCashTestnet3ForkBlock, _ = chainhash.NewHashFromStr("00000000f17c850672894b9a75b63a1e72830bbd5f4c8889b5c1a80e7faef138")

	testnet3Prev, _ := chainhash.NewHashFromStr("0000000000001e8cdb2d98471a5c60bdbddbe644b9ad08e17a97b3a7dce1e332")
	testnet3Merk, _ := chainhash.NewHashFromStr("f675c565b293be2ad808b01b0a763557c8874e4aefe7f2eea0dab91b1f60ec45")
	testnet3Checkpoints = append(testnet3Checkpoints, Checkpoint{
		Height: 1151136,
		Header: wire.BlockHeader{
			Version:    536870912,
			PrevBlock:  *testnet3Prev,
			MerkleRoot: *testnet3Merk,
			Timestamp:  time.Unix(1498950206, 0),
			Bits:       436724869,
			Nonce:      2247874206,
		},
	})
	if testnet3Checkpoints[0].Header.BlockHash().String() != "00000000000002c04de174cf25c993b4dd221eb087c0601a599ff1977e230c99" {
		panic("Invalid checkpoint 0")
	}

	// Regtest
	regtestCheckpoint = Checkpoint{0, chaincfg.RegressionNetParams.GenesisBlock.Header}
}

func GetCheckpoint(walletCreationDate time.Time, params *chaincfg.Params) Checkpoint {
	switch params.Name {
	case chaincfg.MainNetParams.Name:
		for i := len(mainnetCheckpoints) - 1; i >= 0; i-- {
			if walletCreationDate.After(mainnetCheckpoints[i].Header.Timestamp) {
				return mainnetCheckpoints[i]
			}
		}
		return mainnetCheckpoints[0]
	case chaincfg.TestNet3Params.Name:
		for i := len(testnet3Checkpoints) - 1; i >= 0; i-- {
			if walletCreationDate.After(testnet3Checkpoints[i].Header.Timestamp) {
				return testnet3Checkpoints[i]
			}
		}
		return testnet3Checkpoints[0]

	default:
		return regtestCheckpoint
	}
}

func ForkHeight(params *chaincfg.Params) uint32 {
	switch params.Name {
	case chaincfg.MainNetParams.Name:
		return 478559
	case chaincfg.TestNet3Params.Name:
		return 1155875
	}
	return 0
}

func IsForkBlock(params *chaincfg.Params, header wire.BlockHeader) bool {
	ckHash := header.BlockHash()
	switch params.Name {
	case chaincfg.MainNetParams.Name:
		return ckHash.IsEqual(BitcoinCashMainnetForkBlock)
	case chaincfg.TestNet3Params.Name:
		return ckHash.IsEqual(BitcoinCashTestnet3ForkBlock)
	}
	return false
}
<|endoftext|>


<commit_before>package messenger

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

const (
	// ProfileURL is the API endpoint used for retrieving profiles.
	// Used in the form: https://graph.facebook.com/v2.6/<USER_ID>?fields=first_name,last_name,profile_pic&access_token=<PAGE_ACCESS_TOKEN>
	ProfileURL = "https://graph.facebook.com/v2.6/"
)

// Options are the settings used when creating a Messenger client.
type Options struct {
	// Verify sets whether or not to be in the "verify" mode. Used for
	// verifying webhooks on the Facebook Developer Portal.
	Verify bool
	// VerifyToken is the token to be used when verifying the webhook. Is set
	// when the webhook is created.
	VerifyToken string
	// Token is the access token of the Facebook page to send messages from.
	Token string
	// WebhookURL is where the Messenger client should listen for webhook events.
	WebhookURL string
}

// MessageHandler is a handler used for responding to a message containing text.
type MessageHandler func(Message, *Response)

// DeliveryHandler is a handler used for responding to a read receipt.
type DeliveryHandler func(Delivery, *Response)

// PostBackHandler is a handler used postback callbacks.
type PostBackHandler func(PostBack, *Response)

// Messenger is the client which manages communication with the Messenger Platform API.
type Messenger struct {
	mux              *http.ServeMux
	messageHandlers  []MessageHandler
	deliveryHandlers []DeliveryHandler
	postBackHandlers []PostBackHandler
	token            string
	verifyHandler    func(http.ResponseWriter, *http.Request)
}

// New creates a new Messenger. You pass in Options in order to affect settings.
func New(mo Options) *Messenger {
	m := &Messenger{
		mux:   http.NewServeMux(),
		token: mo.Token,
	}

	m.verifyHandler = newVerifyHandler(mo.VerifyToken)
	m.mux.HandleFunc(mo.WebhookURL, m.handle)

	return m
}

// HandleMessage adds a new MessageHandler to the Messenger which will be triggered
// when a message is received by the client.
func (m *Messenger) HandleMessage(f MessageHandler) {
	m.messageHandlers = append(m.messageHandlers, f)
}

// HandleDelivery adds a new DeliveryHandler to the Messenger which will be triggered
// when a previously sent message is read by the recipient.
func (m *Messenger) HandleDelivery(f DeliveryHandler) {
	m.deliveryHandlers = append(m.deliveryHandlers, f)
}

// HandlePostBack adds a new PostBackHandler to the Messenger
func (m *Messenger) HandlePostBack(f PostBackHandler) {
	m.postBackHandlers = append(m.postBackHandlers, f)
}

// Handler returns the Messenger in HTTP client form.
func (m *Messenger) Handler() http.Handler {
	return m.mux
}

// ProfileByID retrieves the Facebook user associated with that ID
func (m *Messenger) ProfileByID(id int64) (Profile, error) {
	p := Profile{}
	url := fmt.Sprintf("%v%v", ProfileURL, id)

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return p, err
	}

	req.URL.RawQuery = "fields=first_name,last_name,profile_pic&access_token=" + m.token

	client := &http.Client{}
	resp, err := client.Do(req)
	defer resp.Body.Close()

	err = json.NewDecoder(resp.Body).Decode(&p)

	return p, err
}

// handle is the internal HTTP handler for the webhooks.
func (m *Messenger) handle(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		m.verifyHandler(w, r)
		return
	}

	var rec Receive

	err := json.NewDecoder(r.Body).Decode(&rec)
	if err != nil {
		fmt.Println(err)
		fmt.Fprintln(w, `{status: 'not ok'}`)
		return
	}

	if rec.Object != "page" {
		fmt.Println("Object is not page, undefined behaviour. Got", rec.Object)
	}

	m.dispatch(rec)

	fmt.Fprintln(w, `{status: 'ok'}`)
}

// dispatch triggers all of the relevant handlers when a webhook event is received.
func (m *Messenger) dispatch(r Receive) {
	for _, entry := range r.Entry {
		for _, info := range entry.Messaging {
			a := m.classify(info, entry)
			if a == UnknownAction {
				fmt.Println("Unknown action:", info)
				continue
			}

			resp := &Response{
				to:    Recipient{info.Sender.ID},
				token: m.token,
			}

			switch a {
			case TextAction:
				for _, f := range m.messageHandlers {
					message := *info.Message
					message.Sender = info.Sender
					message.Recipient = info.Recipient
					message.Time = time.Unix(info.Timestamp, 0)
					f(message, resp)
				}
			case DeliveryAction:
				for _, f := range m.deliveryHandlers {
					f(*info.Delivery, resp)
				}
			case PostBackAction:
				for _, f := range m.postBackHandlers {
					message := *info.PostBack
					message.Sender = info.Sender
					message.Recipient = info.Recipient
					message.Time = time.Unix(info.Timestamp, 0)
					f(message, resp)
				}
			}
		}
	}
}

// classify determines what type of message a webhook event is.
func (m *Messenger) classify(info MessageInfo, e Entry) Action {
	if info.Message != nil {
		return TextAction
	} else if info.Delivery != nil {
		return DeliveryAction
	} else if info.PostBack != nil {
		return PostBackAction
	}
	return UnknownAction
}

// newVerifyHandler returns a function which can be used to handle webhook verification
func newVerifyHandler(token string) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.FormValue("hub.verify_token") == token {
			fmt.Fprintln(w, r.FormValue("hub.challenge"))
			return
		}
		fmt.Fprintln(w, "Incorrect verify token.")
	}
}
<commit_msg>Add "/" as default WebhookURL<commit_after>package messenger

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

const (
	// ProfileURL is the API endpoint used for retrieving profiles.
	// Used in the form: https://graph.facebook.com/v2.6/<USER_ID>?fields=first_name,last_name,profile_pic&access_token=<PAGE_ACCESS_TOKEN>
	ProfileURL = "https://graph.facebook.com/v2.6/"
)

// Options are the settings used when creating a Messenger client.
type Options struct {
	// Verify sets whether or not to be in the "verify" mode. Used for
	// verifying webhooks on the Facebook Developer Portal.
	Verify bool
	// VerifyToken is the token to be used when verifying the webhook. Is set
	// when the webhook is created.
	VerifyToken string
	// Token is the access token of the Facebook page to send messages from.
	Token string
	// WebhookURL is where the Messenger client should listen for webhook events. Leaving the string blank implies a path of "/".
	WebhookURL string
}

// MessageHandler is a handler used for responding to a message containing text.
type MessageHandler func(Message, *Response)

// DeliveryHandler is a handler used for responding to a read receipt.
type DeliveryHandler func(Delivery, *Response)

// PostBackHandler is a handler used postback callbacks.
type PostBackHandler func(PostBack, *Response)

// Messenger is the client which manages communication with the Messenger Platform API.
type Messenger struct {
	mux              *http.ServeMux
	messageHandlers  []MessageHandler
	deliveryHandlers []DeliveryHandler
	postBackHandlers []PostBackHandler
	token            string
	verifyHandler    func(http.ResponseWriter, *http.Request)
}

// New creates a new Messenger. You pass in Options in order to affect settings.
func New(mo Options) *Messenger {
	m := &Messenger{
		mux:   http.NewServeMux(),
		token: mo.Token,
	}

	if mo.WebhookURL == "" {
		mo.WebhookURL = "/"
	}

	m.verifyHandler = newVerifyHandler(mo.VerifyToken)
	m.mux.HandleFunc(mo.WebhookURL, m.handle)

	return m
}

// HandleMessage adds a new MessageHandler to the Messenger which will be triggered
// when a message is received by the client.
func (m *Messenger) HandleMessage(f MessageHandler) {
	m.messageHandlers = append(m.messageHandlers, f)
}

// HandleDelivery adds a new DeliveryHandler to the Messenger which will be triggered
// when a previously sent message is read by the recipient.
func (m *Messenger) HandleDelivery(f DeliveryHandler) {
	m.deliveryHandlers = append(m.deliveryHandlers, f)
}

// HandlePostBack adds a new PostBackHandler to the Messenger
func (m *Messenger) HandlePostBack(f PostBackHandler) {
	m.postBackHandlers = append(m.postBackHandlers, f)
}

// Handler returns the Messenger in HTTP client form.
func (m *Messenger) Handler() http.Handler {
	return m.mux
}

// ProfileByID retrieves the Facebook user associated with that ID
func (m *Messenger) ProfileByID(id int64) (Profile, error) {
	p := Profile{}
	url := fmt.Sprintf("%v%v", ProfileURL, id)

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return p, err
	}

	req.URL.RawQuery = "fields=first_name,last_name,profile_pic&access_token=" + m.token

	client := &http.Client{}
	resp, err := client.Do(req)
	defer resp.Body.Close()

	err = json.NewDecoder(resp.Body).Decode(&p)

	return p, err
}

// handle is the internal HTTP handler for the webhooks.
func (m *Messenger) handle(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		m.verifyHandler(w, r)
		return
	}

	var rec Receive

	err := json.NewDecoder(r.Body).Decode(&rec)
	if err != nil {
		fmt.Println("could not decode response:", err)
		fmt.Fprintln(w, `{status: 'not ok'}`)
		return
	}

	if rec.Object != "page" {
		fmt.Println("Object is not page, undefined behaviour. Got", rec.Object)
	}

	m.dispatch(rec)

	fmt.Fprintln(w, `{status: 'ok'}`)
}

// dispatch triggers all of the relevant handlers when a webhook event is received.
func (m *Messenger) dispatch(r Receive) {
	for _, entry := range r.Entry {
		for _, info := range entry.Messaging {
			a := m.classify(info, entry)
			if a == UnknownAction {
				fmt.Println("Unknown action:", info)
				continue
			}

			resp := &Response{
				to:    Recipient{info.Sender.ID},
				token: m.token,
			}

			switch a {
			case TextAction:
				for _, f := range m.messageHandlers {
					message := *info.Message
					message.Sender = info.Sender
					message.Recipient = info.Recipient
					message.Time = time.Unix(info.Timestamp, 0)
					f(message, resp)
				}
			case DeliveryAction:
				for _, f := range m.deliveryHandlers {
					f(*info.Delivery, resp)
				}
			case PostBackAction:
				for _, f := range m.postBackHandlers {
					message := *info.PostBack
					message.Sender = info.Sender
					message.Recipient = info.Recipient
					message.Time = time.Unix(info.Timestamp, 0)
					f(message, resp)
				}
			}
		}
	}
}

// classify determines what type of message a webhook event is.
func (m *Messenger) classify(info MessageInfo, e Entry) Action {
	if info.Message != nil {
		return TextAction
	} else if info.Delivery != nil {
		return DeliveryAction
	} else if info.PostBack != nil {
		return PostBackAction
	}
	return UnknownAction
}

// newVerifyHandler returns a function which can be used to handle webhook verification
func newVerifyHandler(token string) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.FormValue("hub.verify_token") == token {
			fmt.Fprintln(w, r.FormValue("hub.challenge"))
			return
		}
		fmt.Fprintln(w, "Incorrect verify token.")
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Istio Authors
//
// 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 server

import (
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"google.golang.org/grpc"

	mcp "istio.io/api/mcp/v1alpha1"
	"istio.io/istio/galley/pkg/meshconfig"
	"istio.io/istio/galley/pkg/metadata"
	kubeMeta "istio.io/istio/galley/pkg/metadata/kube"
	"istio.io/istio/galley/pkg/runtime"
	"istio.io/istio/galley/pkg/runtime/groups"
	"istio.io/istio/galley/pkg/source/fs"
	kubeSource "istio.io/istio/galley/pkg/source/kube"
	"istio.io/istio/galley/pkg/source/kube/client"
	"istio.io/istio/galley/pkg/source/kube/dynamic/converter"
	"istio.io/istio/galley/pkg/source/kube/schema"
	"istio.io/istio/galley/pkg/source/kube/schema/check"
	"istio.io/istio/pkg/ctrlz"
	"istio.io/istio/pkg/log"
	"istio.io/istio/pkg/mcp/creds"
	"istio.io/istio/pkg/mcp/monitoring"
	"istio.io/istio/pkg/mcp/server"
	"istio.io/istio/pkg/mcp/snapshot"
	"istio.io/istio/pkg/mcp/source"
	"istio.io/istio/pkg/probe"
	"istio.io/istio/pkg/version"
)

var scope = log.RegisterScope("server", "Galley server debugging", 0)

// Server is the main entry point into the Galley code.
type Server struct {
	serveWG    sync.WaitGroup
	grpcServer *grpc.Server
	processor  *runtime.Processor
	mcp        *server.Server
	mcpSource  *source.Server
	reporter   monitoring.Reporter
	listener   net.Listener
	controlZ   *ctrlz.Server
	stopCh     chan struct{}
	callOut    *callout
}

type patchTable struct {
	newKubeFromConfigFile       func(string) (client.Interfaces, error)
	verifyResourceTypesPresence func(client.Interfaces) error
	newSource                   func(client.Interfaces, time.Duration, *schema.Instance, *converter.Config) (runtime.Source, error)
	netListen                   func(network, address string) (net.Listener, error)
	newMeshConfigCache          func(path string) (meshconfig.Cache, error)
	mcpMetricReporter           func(string) monitoring.Reporter
	fsNew                       func(string, *schema.Instance, *converter.Config) (runtime.Source, error)
}

func defaultPatchTable() patchTable {
	return patchTable{
		newKubeFromConfigFile:       client.NewKubeFromConfigFile,
		verifyResourceTypesPresence: check.ResourceTypesPresence,
		newSource:                   kubeSource.New,
		netListen:                   net.Listen,
		mcpMetricReporter:           func(prefix string) monitoring.Reporter { return monitoring.NewStatsContext(prefix) },
		newMeshConfigCache:          func(path string) (meshconfig.Cache, error) { return meshconfig.NewCacheFromFile(path) },
		fsNew:                       fs.New,
	}
}

// New returns a new instance of a Server.
func New(a *Args) (*Server, error) {
	return newServer(a, defaultPatchTable())
}

func newServer(a *Args, p patchTable) (*Server, error) {
	var err error
	s := &Server{}

	defer func() {
		// If returns with error, need to close the server.
		if err != nil {
			_ = s.Close()
		}
	}()

	mesh, err := p.newMeshConfigCache(a.MeshConfigFile)
	if err != nil {
		return nil, err
	}
	converterCfg := &converter.Config{
		Mesh:         mesh,
		DomainSuffix: a.DomainSuffix,
	}

	sourceSchema := getSourceSchema(a)

	var src runtime.Source
	if a.ConfigPath != "" {
		src, err = p.fsNew(a.ConfigPath, sourceSchema, converterCfg)
		if err != nil {
			return nil, err
		}
	} else {
		k, err := p.newKubeFromConfigFile(a.KubeConfig)
		if err != nil {
			return nil, err
		}
		if !a.DisableResourceReadyCheck {
			if err := p.verifyResourceTypesPresence(k); err != nil {
				return nil, err
			}
		}
		src, err = p.newSource(k, a.ResyncPeriod, sourceSchema, converterCfg)
		if err != nil {
			return nil, err
		}
	}

	processorCfg := runtime.Config{
		DomainSuffix: a.DomainSuffix,
		Mesh:         mesh,
	}
	distributor := snapshot.New(groups.IndexFunction)
	s.processor = runtime.NewProcessor(src, distributor, &processorCfg)

	var grpcOptions []grpc.ServerOption
	grpcOptions = append(grpcOptions, grpc.MaxConcurrentStreams(uint32(a.MaxConcurrentStreams)))
	grpcOptions = append(grpcOptions, grpc.MaxRecvMsgSize(int(a.MaxReceivedMessageSize)))

	s.stopCh = make(chan struct{})
	var checker server.AuthChecker = server.NewAllowAllChecker()
	if !a.Insecure {
		checker, err = watchAccessList(s.stopCh, a.AccessListFile)
		if err != nil {
			return nil, err
		}

		watcher, err := creds.PollFiles(s.stopCh, a.CredentialOptions)
		if err != nil {
			return nil, err
		}
		credentials := creds.CreateForServer(watcher)

		grpcOptions = append(grpcOptions, grpc.Creds(credentials))
	}
	grpc.EnableTracing = a.EnableGRPCTracing
	s.grpcServer = grpc.NewServer(grpcOptions...)

	s.reporter = p.mcpMetricReporter("galley/mcp/source")

	options := &source.Options{
		Watcher:            distributor,
		Reporter:           s.reporter,
		CollectionsOptions: source.CollectionOptionsFromSlice(metadata.Types.Collections()),
	}

	if a.SinkAddress != "" {
		s.callOut, err = newCallout(a.SinkAddress, a.SinkAuthMode, options)
		if err != nil {
			s.callOut = nil
			scope.Fatalf("Callout could not be initialized: %v", err)
		}
	}

	s.mcp = server.New(options, checker)

	serverOptions := &source.ServerOptions{AuthChecker: checker}
	s.mcpSource = source.NewServer(options, serverOptions)

	// get the network stuff setup
	network := "tcp"
	var address string
	idx := strings.Index(a.APIAddress, "://")
	if idx < 0 {
		address = a.APIAddress
	} else {
		network = a.APIAddress[:idx]
		address = a.APIAddress[idx+3:]
	}

	if s.listener, err = p.netListen(network, address); err != nil {
		return nil, fmt.Errorf("unable to listen: %v", err)
	}

	mcp.RegisterAggregatedMeshConfigServiceServer(s.grpcServer, s.mcp)
	mcp.RegisterResourceSourceServer(s.grpcServer, s.mcpSource)

	s.controlZ, _ = ctrlz.Run(a.IntrospectionOptions, nil)

	return s, nil
}

func getSourceSchema(a *Args) *schema.Instance {
	b := schema.NewBuilder()
	for _, spec := range kubeMeta.Types.All() {
		if !isKindExcluded(a, spec.Kind) {
			b.Add(spec)
		}
	}
	return b.Build()
}

func isKindExcluded(a *Args, kind string) bool {
	for _, excludedKind := range a.ExcludedResourceKinds {
		if kind == excludedKind {
			return true
		}
	}
	return false
}

// Run enables Galley to start receiving gRPC requests on its main API port.
func (s *Server) Run() {
	s.serveWG.Add(1)
	go func() {
		defer s.serveWG.Done()
		err := s.processor.Start()
		if err != nil {
			scope.Errorf("Galley Server unexpectedly terminated: %v", err)
			return
		}

		// start serving
		err = s.grpcServer.Serve(s.listener)
		if err != nil {
			scope.Errorf("Galley Server unexpectedly terminated: %v", err)
		}
	}()
	if s.callOut != nil {
		s.serveWG.Add(1)
		go func() {
			defer s.serveWG.Done()
			s.callOut.Run()
		}()
	}
}

// Address returns the Address of the MCP service.
func (s *Server) Address() net.Addr {
	if s.listener == nil {
		return nil
	}
	return s.listener.Addr()
}

// Close cleans up resources used by the server.
func (s *Server) Close() error {
	if s.stopCh != nil {
		close(s.stopCh)
		s.stopCh = nil
	}

	if s.grpcServer != nil {
		s.grpcServer.GracefulStop()
	}

	if s.controlZ != nil {
		s.controlZ.Close()
	}

	if s.processor != nil {
		s.processor.Stop()
	}

	if s.listener != nil {
		_ = s.listener.Close()
		s.listener = nil
	}

	if s.reporter != nil {
		_ = s.reporter.Close()
	}

	if s.callOut != nil {
		s.callOut.Close()
	}

	if s.grpcServer != nil || s.callOut != nil {
		s.serveWG.Wait()
	}

	// final attempt to purge buffered logs
	_ = log.Sync()

	return nil
}

//RunServer start Galley Server mode
func RunServer(sa *Args, livenessProbeController,
	readinessProbeController probe.Controller) {
	log.Infof("Galley started with %s", sa)
	s, err := New(sa)
	if err != nil {
		log.Fatalf("Unable to initialize Galley Server: %v", err)
	}
	log.Infof("Istio Galley: %s\nStarting gRPC server on %v", version.Info, sa.APIAddress)
	s.Run()
	if livenessProbeController != nil {
		serverLivenessProbe := probe.NewProbe()
		serverLivenessProbe.SetAvailable(nil)
		serverLivenessProbe.RegisterProbe(livenessProbeController, "serverLiveness")
		defer serverLivenessProbe.SetAvailable(errors.New("stopped"))
	}
	if readinessProbeController != nil {
		serverReadinessProbe := probe.NewProbe()
		serverReadinessProbe.SetAvailable(nil)
		serverReadinessProbe.RegisterProbe(readinessProbeController, "serverReadiness")
		defer serverReadinessProbe.SetAvailable(errors.New("stopped"))
	}

	s.serveWG.Wait()
	_ = s.Close()
}
<commit_msg>Fixing race condition in Galley Server.Close() (#11484)<commit_after>// Copyright 2018 Istio Authors
//
// 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 server

import (
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"google.golang.org/grpc"

	mcp "istio.io/api/mcp/v1alpha1"
	"istio.io/istio/galley/pkg/meshconfig"
	"istio.io/istio/galley/pkg/metadata"
	kubeMeta "istio.io/istio/galley/pkg/metadata/kube"
	"istio.io/istio/galley/pkg/runtime"
	"istio.io/istio/galley/pkg/runtime/groups"
	"istio.io/istio/galley/pkg/source/fs"
	kubeSource "istio.io/istio/galley/pkg/source/kube"
	"istio.io/istio/galley/pkg/source/kube/client"
	"istio.io/istio/galley/pkg/source/kube/dynamic/converter"
	"istio.io/istio/galley/pkg/source/kube/schema"
	"istio.io/istio/galley/pkg/source/kube/schema/check"
	"istio.io/istio/pkg/ctrlz"
	"istio.io/istio/pkg/log"
	"istio.io/istio/pkg/mcp/creds"
	"istio.io/istio/pkg/mcp/monitoring"
	"istio.io/istio/pkg/mcp/server"
	"istio.io/istio/pkg/mcp/snapshot"
	"istio.io/istio/pkg/mcp/source"
	"istio.io/istio/pkg/probe"
	"istio.io/istio/pkg/version"
)

var scope = log.RegisterScope("server", "Galley server debugging", 0)

// Server is the main entry point into the Galley code.
type Server struct {
	serveWG       sync.WaitGroup
	grpcServer    *grpc.Server
	processor     *runtime.Processor
	mcp           *server.Server
	mcpSource     *source.Server
	reporter      monitoring.Reporter
	listenerMutex sync.Mutex
	listener      net.Listener
	controlZ      *ctrlz.Server
	stopCh        chan struct{}
	callOut       *callout
}

type patchTable struct {
	newKubeFromConfigFile       func(string) (client.Interfaces, error)
	verifyResourceTypesPresence func(client.Interfaces) error
	newSource                   func(client.Interfaces, time.Duration, *schema.Instance, *converter.Config) (runtime.Source, error)
	netListen                   func(network, address string) (net.Listener, error)
	newMeshConfigCache          func(path string) (meshconfig.Cache, error)
	mcpMetricReporter           func(string) monitoring.Reporter
	fsNew                       func(string, *schema.Instance, *converter.Config) (runtime.Source, error)
}

func defaultPatchTable() patchTable {
	return patchTable{
		newKubeFromConfigFile:       client.NewKubeFromConfigFile,
		verifyResourceTypesPresence: check.ResourceTypesPresence,
		newSource:                   kubeSource.New,
		netListen:                   net.Listen,
		mcpMetricReporter:           func(prefix string) monitoring.Reporter { return monitoring.NewStatsContext(prefix) },
		newMeshConfigCache:          func(path string) (meshconfig.Cache, error) { return meshconfig.NewCacheFromFile(path) },
		fsNew:                       fs.New,
	}
}

// New returns a new instance of a Server.
func New(a *Args) (*Server, error) {
	return newServer(a, defaultPatchTable())
}

func newServer(a *Args, p patchTable) (*Server, error) {
	var err error
	s := &Server{}

	defer func() {
		// If returns with error, need to close the server.
		if err != nil {
			_ = s.Close()
		}
	}()

	mesh, err := p.newMeshConfigCache(a.MeshConfigFile)
	if err != nil {
		return nil, err
	}
	converterCfg := &converter.Config{
		Mesh:         mesh,
		DomainSuffix: a.DomainSuffix,
	}

	sourceSchema := getSourceSchema(a)

	var src runtime.Source
	if a.ConfigPath != "" {
		src, err = p.fsNew(a.ConfigPath, sourceSchema, converterCfg)
		if err != nil {
			return nil, err
		}
	} else {
		k, err := p.newKubeFromConfigFile(a.KubeConfig)
		if err != nil {
			return nil, err
		}
		if !a.DisableResourceReadyCheck {
			if err := p.verifyResourceTypesPresence(k); err != nil {
				return nil, err
			}
		}
		src, err = p.newSource(k, a.ResyncPeriod, sourceSchema, converterCfg)
		if err != nil {
			return nil, err
		}
	}

	processorCfg := runtime.Config{
		DomainSuffix: a.DomainSuffix,
		Mesh:         mesh,
	}
	distributor := snapshot.New(groups.IndexFunction)
	s.processor = runtime.NewProcessor(src, distributor, &processorCfg)

	var grpcOptions []grpc.ServerOption
	grpcOptions = append(grpcOptions, grpc.MaxConcurrentStreams(uint32(a.MaxConcurrentStreams)))
	grpcOptions = append(grpcOptions, grpc.MaxRecvMsgSize(int(a.MaxReceivedMessageSize)))

	s.stopCh = make(chan struct{})
	var checker server.AuthChecker = server.NewAllowAllChecker()
	if !a.Insecure {
		checker, err = watchAccessList(s.stopCh, a.AccessListFile)
		if err != nil {
			return nil, err
		}

		watcher, err := creds.PollFiles(s.stopCh, a.CredentialOptions)
		if err != nil {
			return nil, err
		}
		credentials := creds.CreateForServer(watcher)

		grpcOptions = append(grpcOptions, grpc.Creds(credentials))
	}
	grpc.EnableTracing = a.EnableGRPCTracing
	s.grpcServer = grpc.NewServer(grpcOptions...)

	s.reporter = p.mcpMetricReporter("galley/mcp/source")

	options := &source.Options{
		Watcher:            distributor,
		Reporter:           s.reporter,
		CollectionsOptions: source.CollectionOptionsFromSlice(metadata.Types.Collections()),
	}

	if a.SinkAddress != "" {
		s.callOut, err = newCallout(a.SinkAddress, a.SinkAuthMode, options)
		if err != nil {
			s.callOut = nil
			scope.Fatalf("Callout could not be initialized: %v", err)
		}
	}

	s.mcp = server.New(options, checker)

	serverOptions := &source.ServerOptions{AuthChecker: checker}
	s.mcpSource = source.NewServer(options, serverOptions)

	// get the network stuff setup
	network := "tcp"
	var address string
	idx := strings.Index(a.APIAddress, "://")
	if idx < 0 {
		address = a.APIAddress
	} else {
		network = a.APIAddress[:idx]
		address = a.APIAddress[idx+3:]
	}

	if s.listener, err = p.netListen(network, address); err != nil {
		return nil, fmt.Errorf("unable to listen: %v", err)
	}

	mcp.RegisterAggregatedMeshConfigServiceServer(s.grpcServer, s.mcp)
	mcp.RegisterResourceSourceServer(s.grpcServer, s.mcpSource)

	s.controlZ, _ = ctrlz.Run(a.IntrospectionOptions, nil)

	return s, nil
}

func getSourceSchema(a *Args) *schema.Instance {
	b := schema.NewBuilder()
	for _, spec := range kubeMeta.Types.All() {
		if !isKindExcluded(a, spec.Kind) {
			b.Add(spec)
		}
	}
	return b.Build()
}

func isKindExcluded(a *Args, kind string) bool {
	for _, excludedKind := range a.ExcludedResourceKinds {
		if kind == excludedKind {
			return true
		}
	}
	return false
}

// Run enables Galley to start receiving gRPC requests on its main API port.
func (s *Server) Run() {
	s.serveWG.Add(1)
	go func() {
		defer s.serveWG.Done()
		err := s.processor.Start()
		if err != nil {
			scope.Errorf("Galley Server unexpectedly terminated: %v", err)
			return
		}

		l := s.getListener()
		if l != nil {
			// start serving
			err = s.grpcServer.Serve(l)
			if err != nil {
				scope.Errorf("Galley Server unexpectedly terminated: %v", err)
			}
		}
	}()
	if s.callOut != nil {
		s.serveWG.Add(1)
		go func() {
			defer s.serveWG.Done()
			s.callOut.Run()
		}()
	}
}

func (s *Server) getListener() net.Listener {
	s.listenerMutex.Lock()
	defer s.listenerMutex.Unlock()
	return s.listener
}

// Address returns the Address of the MCP service.
func (s *Server) Address() net.Addr {
	l := s.getListener()
	if l == nil {
		return nil
	}
	return l.Addr()
}

// Close cleans up resources used by the server.
func (s *Server) Close() error {
	if s.stopCh != nil {
		close(s.stopCh)
		s.stopCh = nil
	}

	if s.grpcServer != nil {
		s.grpcServer.GracefulStop()
	}

	if s.controlZ != nil {
		s.controlZ.Close()
	}

	if s.processor != nil {
		s.processor.Stop()
	}

	s.listenerMutex.Lock()
	if s.listener != nil {
		_ = s.listener.Close()
		s.listener = nil
	}
	s.listenerMutex.Unlock()

	if s.reporter != nil {
		_ = s.reporter.Close()
	}

	if s.callOut != nil {
		s.callOut.Close()
	}

	if s.grpcServer != nil || s.callOut != nil {
		s.serveWG.Wait()
	}

	// final attempt to purge buffered logs
	_ = log.Sync()

	return nil
}

//RunServer start Galley Server mode
func RunServer(sa *Args, livenessProbeController,
	readinessProbeController probe.Controller) {
	log.Infof("Galley started with %s", sa)
	s, err := New(sa)
	if err != nil {
		log.Fatalf("Unable to initialize Galley Server: %v", err)
	}
	log.Infof("Istio Galley: %s\nStarting gRPC server on %v", version.Info, sa.APIAddress)
	s.Run()
	if livenessProbeController != nil {
		serverLivenessProbe := probe.NewProbe()
		serverLivenessProbe.SetAvailable(nil)
		serverLivenessProbe.RegisterProbe(livenessProbeController, "serverLiveness")
		defer serverLivenessProbe.SetAvailable(errors.New("stopped"))
	}
	if readinessProbeController != nil {
		serverReadinessProbe := probe.NewProbe()
		serverReadinessProbe.SetAvailable(nil)
		serverReadinessProbe.RegisterProbe(readinessProbeController, "serverReadiness")
		defer serverReadinessProbe.SetAvailable(errors.New("stopped"))
	}

	s.serveWG.Wait()
	_ = s.Close()
}
<|endoftext|>


<commit_before>package cloudwatch

import (
	"math/rand"
	"testing"
	"time"

	"github.com/Pallinder/go-randomdata"
	"github.com/gliderlabs/logspout/router"
)

const NumMessages = 25000000

func TestCloudWatchAdapter(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode.")
	}

	route := &router.Route{Address: "logspout-cloudwatch"}
	messages := make(chan *router.Message)

	adapter, err := NewAdapter(route)
	if err != nil {
		t.Error(err)
		return
	}

	go adapter.Stream(messages)
	for i := 0; i < NumMessages; i++ {
		messages <- createMessage()
	}

	close(messages)
}

func createMessage() *router.Message {
	data := ""
	timestamp := time.Now()
	random := rand.Intn(100)

	if random == 0 {
		data = randomdata.Paragraph()
	}

	return &router.Message{Data: data, Time: timestamp}
}
<commit_msg>Fix empty message case in integration test.<commit_after>package cloudwatch

import (
	"math/rand"
	"testing"
	"time"

	"github.com/Pallinder/go-randomdata"
	"github.com/gliderlabs/logspout/router"
)

const NumMessages = 250000

func TestCloudWatchAdapter(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode.")
	}

	route := &router.Route{Address: "logspout-cloudwatch"}
	messages := make(chan *router.Message)

	adapter, err := NewAdapter(route)
	if err != nil {
		t.Error(err)
		return
	}

	go adapter.Stream(messages)
	for i := 0; i < NumMessages; i++ {
		messages <- createMessage()
	}

	close(messages)
}

func createMessage() *router.Message {
	data := ""
	timestamp := time.Now()
	random := rand.Intn(100)

	if random != 0 {
		data = randomdata.Paragraph()
	}

	return &router.Message{Data: data, Time: timestamp}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/aybabtme/uniplot/histogram"
)

func mapIterate(initialSize int, numIterations int) []float64 {
	results := make([]float64, numIterations)
	for iteration := 0; iteration < numIterations; iteration++ {
		// initialize
		m := make(map[int]int)
		for i := 0; i < initialSize; i++ {
			m[i] = i
		}

		// iterate the map, adding a value each time
		for k := range m {
			m[k*2] = k * 2
		}
		results[iteration] = float64(len(m))
	}
	return results
}

type result struct {
	initialSize   int
	mapFinalSizes []float64 // The histogram library wants floats
}

func usage() {
	fmt.Print(`
mapwalker is a program to answer a fun toy question: what happens as you insert
into a golang map while traversing it? It gives a histogram of final sizes from
a real golang map, and a simulated map.

`)
	flag.PrintDefaults()
}

func main() {
	flag.Usage = usage
	initialSize := flag.Int("initial", 1024, "initial size of map")
	numIterations := flag.Int("iterations", 1000, "number of iterations to run")
	flag.Parse()

	mapFinalSizes := mapIterate(*initialSize, *numIterations)

	fmt.Printf("Initial size of map: %d\n", *initialSize)
	fmt.Printf("Distribution of final size of map over %d iterations\n", *numIterations)
	hist := histogram.Hist(10, mapFinalSizes)
	histogram.Fprint(os.Stdout, hist, histogram.Linear(20))
}
<commit_msg>fix bug where the first half of inserts were not modifying the map<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/aybabtme/uniplot/histogram"
)

func mapIterate(initialSize int, numIterations int) []float64 {
	results := make([]float64, numIterations)
	for iteration := 0; iteration < numIterations; iteration++ {
		// initialize
		m := make(map[int]int)
		for i := 0; i < initialSize; i++ {
			m[i] = i
		}

		// iterate the map, adding a value each time
		for k := range m {
			m[k+initialSize] = k
		}
		results[iteration] = float64(len(m))
	}
	return results
}

type result struct {
	initialSize   int
	mapFinalSizes []float64 // The histogram library wants floats
}

func usage() {
	fmt.Print(`
mapwalker is a program to answer a fun toy question: what happens as you insert
into a golang map while traversing it? It gives a histogram of final sizes from
a real golang map, and a simulated map.

`)
	flag.PrintDefaults()
}

func main() {
	flag.Usage = usage
	initialSize := flag.Int("initial", 1024, "initial size of map")
	numIterations := flag.Int("iterations", 1000, "number of iterations to run")
	flag.Parse()

	mapFinalSizes := mapIterate(*initialSize, *numIterations)

	fmt.Printf("Initial size of map: %d\n", *initialSize)
	fmt.Printf("Distribution of final size of map over %d iterations\n", *numIterations)
	hist := histogram.Hist(10, mapFinalSizes)
	histogram.Fprint(os.Stdout, hist, histogram.Linear(20))
}
<|endoftext|>


<commit_before>// Automatically generated by MockGen. DO NOT EDIT!
// Source: github.com/smancke/guble/store (interfaces: KVStore)

package gcm

import (
	gomock "github.com/golang/mock/gomock"
)

// Mock of KVStore interface
type MockKVStore struct {
	ctrl     *gomock.Controller
	recorder *_MockKVStoreRecorder
}

// Recorder for MockKVStore (not exported)
type _MockKVStoreRecorder struct {
	mock *MockKVStore
}

func NewMockKVStore(ctrl *gomock.Controller) *MockKVStore {
	mock := &MockKVStore{ctrl: ctrl}
	mock.recorder = &_MockKVStoreRecorder{mock}
	return mock
}

func (_m *MockKVStore) EXPECT() *_MockKVStoreRecorder {
	return _m.recorder
}

func (_m *MockKVStore) Delete(_param0 string, _param1 string) error {
	ret := _m.ctrl.Call(_m, "Delete", _param0, _param1)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Delete(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Delete", arg0, arg1)
}

func (_m *MockKVStore) Get(_param0 string, _param1 string) ([]byte, bool, error) {
	ret := _m.ctrl.Call(_m, "Get", _param0, _param1)
	ret0, _ := ret[0].([]byte)
	ret1, _ := ret[1].(bool)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

func (_mr *_MockKVStoreRecorder) Get(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Get", arg0, arg1)
}

func (_m *MockKVStore) Iterate(_param0 string, _param1 string) chan [2]string {
	ret := _m.ctrl.Call(_m, "Iterate", _param0, _param1)
	ret0, _ := ret[0].(chan [2]string)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Iterate(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Iterate", arg0, arg1)
}

func (_m *MockKVStore) IterateKeys(_param0 string, _param1 string) chan string {
	ret := _m.ctrl.Call(_m, "IterateKeys", _param0, _param1)
	ret0, _ := ret[0].(chan string)
	return ret0
}

func (_mr *_MockKVStoreRecorder) IterateKeys(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "IterateKeys", arg0, arg1)
}

func (_m *MockKVStore) Put(_param0 string, _param1 string, _param2 []byte) error {
	ret := _m.ctrl.Call(_m, "Put", _param0, _param1, _param2)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Put(arg0, arg1, arg2 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Put", arg0, arg1, arg2)
}
<commit_msg>Regenerated the mocks for the kvStore Interface<commit_after>// Automatically generated by MockGen. DO NOT EDIT!
// Source: github.com/smancke/guble/store (interfaces: KVStore)

package gcm

import (
	gomock "github.com/golang/mock/gomock"
)

// Mock of KVStore interface
type MockKVStore struct {
	ctrl     *gomock.Controller
	recorder *_MockKVStoreRecorder
}

// Recorder for MockKVStore (not exported)
type _MockKVStoreRecorder struct {
	mock *MockKVStore
}

func NewMockKVStore(ctrl *gomock.Controller) *MockKVStore {
	mock := &MockKVStore{ctrl: ctrl}
	mock.recorder = &_MockKVStoreRecorder{mock}
	return mock
}

func (_m *MockKVStore) EXPECT() *_MockKVStoreRecorder {
	return _m.recorder
}

func (_m *MockKVStore) Check() error {
	ret := _m.ctrl.Call(_m, "Check")
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Check() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Check")
}

func (_m *MockKVStore) Delete(_param0 string, _param1 string) error {
	ret := _m.ctrl.Call(_m, "Delete", _param0, _param1)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Delete(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Delete", arg0, arg1)
}

func (_m *MockKVStore) Get(_param0 string, _param1 string) ([]byte, bool, error) {
	ret := _m.ctrl.Call(_m, "Get", _param0, _param1)
	ret0, _ := ret[0].([]byte)
	ret1, _ := ret[1].(bool)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

func (_mr *_MockKVStoreRecorder) Get(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Get", arg0, arg1)
}

func (_m *MockKVStore) Iterate(_param0 string, _param1 string) chan [2]string {
	ret := _m.ctrl.Call(_m, "Iterate", _param0, _param1)
	ret0, _ := ret[0].(chan [2]string)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Iterate(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Iterate", arg0, arg1)
}

func (_m *MockKVStore) IterateKeys(_param0 string, _param1 string) chan string {
	ret := _m.ctrl.Call(_m, "IterateKeys", _param0, _param1)
	ret0, _ := ret[0].(chan string)
	return ret0
}

func (_mr *_MockKVStoreRecorder) IterateKeys(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "IterateKeys", arg0, arg1)
}

func (_m *MockKVStore) Put(_param0 string, _param1 string, _param2 []byte) error {
	ret := _m.ctrl.Call(_m, "Put", _param0, _param1, _param2)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockKVStoreRecorder) Put(arg0, arg1, arg2 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Put", arg0, arg1, arg2)
}
<|endoftext|>


<commit_before>package bpmon

import "testing"

type testsets struct {
	op  string
	val []bool
	res bool
}

var TestSets = []testsets{
	{"AND", []bool{true, true, true}, true},
	{"AND", []bool{true}, true},
	{"AND", []bool{}, true},
	{"AND", []bool{true, false, true}, false},
	{"AND", []bool{false}, false},
	{"OR", []bool{true, true, true}, true},
	{"OR", []bool{true}, true},
	{"OR", []bool{}, true},
	{"OR", []bool{true, false, true}, true},
	{"OR", []bool{true, false, false}, true},
	{"OR", []bool{false, false}, false},
	{"OR", []bool{false}, false},
	{"MIN 3", []bool{true, true, true}, true},
	{"MIN 2", []bool{true}, false},
	{"MIN 0", []bool{}, true},
	{"MIN 3", []bool{true, false, true}, false},
	{"MINPERCENT 100", []bool{true, true, true}, true},
	{"MINPERCENT 33.34", []bool{true, false, false}, false},
	{"MINPERCENT 33.33", []bool{true, false, false}, true},
	{"MINPERCENT 0", []bool{false, false}, true},
	{"MINPERCENT 0", []bool{}, true},
	{"MINPERCENT 100", []bool{}, true},
}

func TestOperations(t *testing.T) {
	for _, test := range TestSets {
		res, _ := calculate(test.op, test.val)
		if res != test.res {
			t.Errorf("Expected operation '%s' on data %v to be %v, is %v", test.op, test.val, test.res, res)
		}
	}
}
<commit_msg>typo: plural to sigular<commit_after>package bpmon

import "testing"

type testset struct {
	op  string
	val []bool
	res bool
}

var TestSets = []testset{
	{"AND", []bool{true, true, true}, true},
	{"AND", []bool{true}, true},
	{"AND", []bool{}, true},
	{"AND", []bool{true, false, true}, false},
	{"AND", []bool{false}, false},
	{"OR", []bool{true, true, true}, true},
	{"OR", []bool{true}, true},
	{"OR", []bool{}, true},
	{"OR", []bool{true, false, true}, true},
	{"OR", []bool{true, false, false}, true},
	{"OR", []bool{false, false}, false},
	{"OR", []bool{false}, false},
	{"MIN 3", []bool{true, true, true}, true},
	{"MIN 2", []bool{true}, false},
	{"MIN 0", []bool{}, true},
	{"MIN 3", []bool{true, false, true}, false},
	{"MINPERCENT 100", []bool{true, true, true}, true},
	{"MINPERCENT 33.34", []bool{true, false, false}, false},
	{"MINPERCENT 33.33", []bool{true, false, false}, true},
	{"MINPERCENT 0", []bool{false, false}, true},
	{"MINPERCENT 0", []bool{}, true},
	{"MINPERCENT 100", []bool{}, true},
}

func TestOperations(t *testing.T) {
	for _, test := range TestSets {
		res, _ := calculate(test.op, test.val)
		if res != test.res {
			t.Errorf("Expected operation '%s' on data %v to be %v, is %v", test.op, test.val, test.res, res)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strconv"

	circle "github.com/Shyp/go-circle"
	"github.com/Shyp/go-circle/wait"
	git "github.com/Shyp/go-git"
	"github.com/skratchdot/open-golang/open"
	"golang.org/x/sync/errgroup"
)

const help = `The circle binary interacts with a server that runs your tests.

Usage:

	circle command [arguments]

The commands are:

	open                Open the latest branch build in a browser.
	update              Update to the latest version
	version             Print the current version
	wait                Wait for tests to finish on a branch.
	download-artifacts  Download all artifacts.

Use "circle help [command]" for more information about a command.
`

const downloadUsage = `usage: download-artifacts <build-num>`

func usage() {
	fmt.Fprintf(os.Stderr, help)
	flag.PrintDefaults()
	os.Exit(2)
}

func init() {
	flag.Usage = usage
}

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// Given a set of command line args, return the git branch or an error. Returns
// the current git branch if no argument is specified
func getBranchFromArgs(args []string) (string, error) {
	if len(args) == 0 {
		return git.CurrentBranch()
	} else {
		return args[0], nil
	}
}

func doOpen(flags *flag.FlagSet) {
	args := flags.Args()
	branch, err := getBranchFromArgs(args)
	checkError(err)
	remote, err := git.GetRemoteURL("origin")
	checkError(err)
	cr, err := circle.GetTree(remote.Path, remote.RepoName, branch)
	checkError(err)
	if len(*cr) == 0 {
		fmt.Printf("No results, are you sure there are tests for %s/%s?\n",
			remote.Path, remote.RepoName)
		return
	}
	latestBuild := (*cr)[0]
	open.Start(latestBuild.BuildURL)
}

func doDownload(flags *flag.FlagSet) error {
	buildStr := flags.Arg(0)
	val, err := strconv.Atoi(buildStr)
	if err != nil {
		return err
	}
	remote, err := git.GetRemoteURL("origin")
	if err != nil {
		return err
	}
	arts, err := circle.GetArtifactsForBuild(remote.Path, remote.RepoName, val)
	if err != nil {
		return err
	}
	var g errgroup.Group
	tempDir, err := ioutil.TempDir("", "circle-artifacts")
	if err != nil {
		return err
	}
	for _, art := range arts {
		art := art
		g.Go(func() error {
			return circle.DownloadArtifact(art, tempDir, remote.Path)
		})
	}

	if err := g.Wait(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		return err
	}
	fmt.Fprintf(os.Stderr, "Wrote all artifacts for build %d to %s\n", val, tempDir)
	return nil
}

func main() {
	waitflags := flag.NewFlagSet("wait", flag.ExitOnError)
	openflags := flag.NewFlagSet("open", flag.ExitOnError)
	downloadflags := flag.NewFlagSet("download-artifacts", flag.ExitOnError)
	downloadflags.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\n\n", downloadUsage)
		downloadflags.PrintDefaults()
		os.Exit(1)
	}

	flag.Parse()
	args := flag.Args()
	if len(args) < 1 {
		usage()
		return
	}
	switch flag.Arg(0) {
	case "open":
		openflags.Parse(os.Args[2:])
		doOpen(openflags)
	case "update":
		err := equinoxUpdate()
		checkError(err)
	case "version":
		fmt.Fprintf(os.Stderr, "circle version %s\n", circle.VERSION)
		os.Exit(1)
	case "wait":
		waitflags.Parse(os.Args[2:])
		args := waitflags.Args()
		branch, err := getBranchFromArgs(args)
		checkError(err)
		err = wait.Wait(branch)
		checkError(err)
	case "download-artifacts":
		if len(args) == 1 {
			fmt.Fprintf(os.Stderr, "usage: download-artifacts <build-number>\n")
			os.Exit(1)
		}
		downloadflags.Parse(args[1:])
		if err := doDownload(downloadflags); err != nil {
			log.Fatal(err)
		}

	default:
		usage()
	}
}
<commit_msg>Add help text for 'circle wait -h' (#16)<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strconv"

	circle "github.com/Shyp/go-circle"
	"github.com/Shyp/go-circle/wait"
	git "github.com/Shyp/go-git"
	"github.com/skratchdot/open-golang/open"
	"golang.org/x/sync/errgroup"
)

const help = `The circle binary interacts with a server that runs your tests.

Usage:

	circle command [arguments]

The commands are:

	open                Open the latest branch build in a browser.
	update              Update to the latest version
	version             Print the current version
	wait                Wait for tests to finish on a branch.
	download-artifacts  Download all artifacts.

Use "circle help [command]" for more information about a command.
`

const downloadUsage = `usage: download-artifacts <build-num>`

func usage() {
	fmt.Fprintf(os.Stderr, help)
	flag.PrintDefaults()
	os.Exit(2)
}

func init() {
	flag.Usage = usage
}

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// Given a set of command line args, return the git branch or an error. Returns
// the current git branch if no argument is specified
func getBranchFromArgs(args []string) (string, error) {
	if len(args) == 0 {
		return git.CurrentBranch()
	} else {
		return args[0], nil
	}
}

func doOpen(flags *flag.FlagSet) {
	args := flags.Args()
	branch, err := getBranchFromArgs(args)
	checkError(err)
	remote, err := git.GetRemoteURL("origin")
	checkError(err)
	cr, err := circle.GetTree(remote.Path, remote.RepoName, branch)
	checkError(err)
	if len(*cr) == 0 {
		fmt.Printf("No results, are you sure there are tests for %s/%s?\n",
			remote.Path, remote.RepoName)
		return
	}
	latestBuild := (*cr)[0]
	open.Start(latestBuild.BuildURL)
}

func doDownload(flags *flag.FlagSet) error {
	buildStr := flags.Arg(0)
	val, err := strconv.Atoi(buildStr)
	if err != nil {
		return err
	}
	remote, err := git.GetRemoteURL("origin")
	if err != nil {
		return err
	}
	arts, err := circle.GetArtifactsForBuild(remote.Path, remote.RepoName, val)
	if err != nil {
		return err
	}
	var g errgroup.Group
	tempDir, err := ioutil.TempDir("", "circle-artifacts")
	if err != nil {
		return err
	}
	for _, art := range arts {
		art := art
		g.Go(func() error {
			return circle.DownloadArtifact(art, tempDir, remote.Path)
		})
	}

	if err := g.Wait(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		return err
	}
	fmt.Fprintf(os.Stderr, "Wrote all artifacts for build %d to %s\n", val, tempDir)
	return nil
}

func main() {
	waitflags := flag.NewFlagSet("wait", flag.ExitOnError)
	waitflags.Usage = func() {
		fmt.Fprintf(os.Stderr, `usage: wait

Wait for builds to complete, then print a descriptive output on
success or failure.
`)
		waitflags.PrintDefaults()
		os.Exit(2)
	}
	openflags := flag.NewFlagSet("open", flag.ExitOnError)
	downloadflags := flag.NewFlagSet("download-artifacts", flag.ExitOnError)
	downloadflags.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\n\n", downloadUsage)
		downloadflags.PrintDefaults()
		os.Exit(1)
	}

	flag.Parse()
	args := flag.Args()
	if len(args) < 1 {
		usage()
		return
	}
	switch flag.Arg(0) {
	case "open":
		openflags.Parse(os.Args[2:])
		doOpen(openflags)
	case "update":
		err := equinoxUpdate()
		checkError(err)
	case "version":
		fmt.Fprintf(os.Stderr, "circle version %s\n", circle.VERSION)
		os.Exit(1)
	case "wait":
		waitflags.Parse(os.Args[2:])
		args := waitflags.Args()
		branch, err := getBranchFromArgs(args)
		checkError(err)
		err = wait.Wait(branch)
		checkError(err)
	case "download-artifacts":
		if len(args) == 1 {
			fmt.Fprintf(os.Stderr, "usage: download-artifacts <build-number>\n")
			os.Exit(1)
		}
		downloadflags.Parse(args[1:])
		if err := doDownload(downloadflags); err != nil {
			log.Fatal(err)
		}

	default:
		usage()
	}
}
<|endoftext|>


<commit_before>package app

import (
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/docker/libcompose/project"
)

// ProjectAction is an adapter to allow the use of ordinary functions as libcompose actions.
// Any function that has the appropriate signature can be register as an action on a codegansta/cli command.
//
// cli.Command{
//		Name:   "ps",
//		Usage:  "List containers",
//		Action: app.WithProject(factory, app.ProjectPs),
//	}
type ProjectAction func(project *project.Project, c *cli.Context)

// BeforeApp is an action that is executed before any cli command.
func BeforeApp(c *cli.Context) error {
	if c.GlobalBool("verbose") {
		logrus.SetLevel(logrus.DebugLevel)
	}
	logrus.Warning("Note: This is an experimental alternate implementation of the Compose CLI (https://github.com/docker/compose)")
	return nil
}

// WithProject is an helper function to create a cli.Command action with a ProjectFactory.
func WithProject(factory ProjectFactory, action ProjectAction) func(context *cli.Context) {
	return func(context *cli.Context) {
		p, err := factory.Create(context)
		if err != nil {
			log.Fatalf("Failed to read project: %v", err)
		}
		action(p, context)
	}
}

// ProjectPs lists the containers.
func ProjectPs(p *project.Project, c *cli.Context) {
	allInfo := project.InfoSet{}
	for name := range p.Configs {
		service, err := p.CreateService(name)
		if err != nil {
			logrus.Fatal(err)
		}

		info, err := service.Info()
		if err != nil {
			logrus.Fatal(err)
		}

		allInfo = append(allInfo, info...)
	}

	os.Stdout.WriteString(allInfo.String())
}

// ProjectPort prints the public port for a port binding.
func ProjectPort(p *project.Project, c *cli.Context) {
	if len(c.Args()) != 2 {
		logrus.Fatalf("Please pass arguments in the form: SERVICE PORT")
	}

	index := c.Int("index")
	protocol := c.String("protocol")

	service, err := p.CreateService(c.Args()[0])
	if err != nil {
		logrus.Fatal(err)
	}

	containers, err := service.Containers()
	if err != nil {
		logrus.Fatal(err)
	}

	if index < 1 || index > len(containers) {
		logrus.Fatalf("Invalid index %d", index)
	}

	output, err := containers[index-1].Port(fmt.Sprintf("%s/%s", c.Args()[1], protocol))
	if err != nil {
		logrus.Fatal(err)
	}
	fmt.Println(output)
}

// ProjectDown brings all services down.
func ProjectDown(p *project.Project, c *cli.Context) {
	err := p.Down(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectBuild builds or rebuilds services.
func ProjectBuild(p *project.Project, c *cli.Context) {
	err := p.Build(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectCreate creates all services but do not start them.
func ProjectCreate(p *project.Project, c *cli.Context) {
	err := p.Create(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectUp brings all services up.
func ProjectUp(p *project.Project, c *cli.Context) {
	err := p.Up(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}

	if !c.Bool("d") {
		wait()
	}
}

// ProjectStart starts services.
func ProjectStart(p *project.Project, c *cli.Context) {
	err := p.Start(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectRestart restarts services.
func ProjectRestart(p *project.Project, c *cli.Context) {
	err := p.Restart(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectLog gets services logs.
func ProjectLog(p *project.Project, c *cli.Context) {
	err := p.Log(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
	wait()
}

// ProjectPull pulls images for services.
func ProjectPull(p *project.Project, c *cli.Context) {
	err := p.Pull(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectDelete delete services.
func ProjectDelete(p *project.Project, c *cli.Context) {
	if !c.Bool("force") && len(c.Args()) == 0 {
		logrus.Fatal("Will not remove all services with out --force")
	}
	err := p.Delete(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectKill forces stop service containers.
func ProjectKill(p *project.Project, c *cli.Context) {
	err := p.Kill(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectScale scales services.
func ProjectScale(p *project.Project, c *cli.Context) {
	// This code is a bit verbose but I wanted to parse everything up front
	order := make([]string, 0, 0)
	serviceScale := make(map[string]int)
	services := make(map[string]project.Service)

	for _, arg := range c.Args() {
		kv := strings.SplitN(arg, "=", 2)
		if len(kv) != 2 {
			logrus.Fatalf("Invalid scale parameter: %s", arg)
		}

		name := kv[0]

		count, err := strconv.Atoi(kv[1])
		if err != nil {
			logrus.Fatalf("Invalid scale parameter: %v", err)
		}

		if _, ok := p.Configs[name]; !ok {
			logrus.Fatalf("%s is not defined in the template", name)
		}

		service, err := p.CreateService(name)
		if err != nil {
			logrus.Fatalf("Failed to lookup service: %s: %v", service, err)
		}

		order = append(order, name)
		serviceScale[name] = count
		services[name] = service
	}

	for _, name := range order {
		scale := serviceScale[name]
		logrus.Infof("Setting scale %s=%d...", name, scale)
		err := services[name].Scale(scale)
		if err != nil {
			logrus.Fatalf("Failed to set the scale %s=%d: %v", name, scale, err)
		}
	}
}

func wait() {
	<-make(chan interface{})
}
<commit_msg>Replacing log package with logrus<commit_after>package app

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/docker/libcompose/project"
)

// ProjectAction is an adapter to allow the use of ordinary functions as libcompose actions.
// Any function that has the appropriate signature can be register as an action on a codegansta/cli command.
//
// cli.Command{
//		Name:   "ps",
//		Usage:  "List containers",
//		Action: app.WithProject(factory, app.ProjectPs),
//	}
type ProjectAction func(project *project.Project, c *cli.Context)

// BeforeApp is an action that is executed before any cli command.
func BeforeApp(c *cli.Context) error {
	if c.GlobalBool("verbose") {
		logrus.SetLevel(logrus.DebugLevel)
	}
	logrus.Warning("Note: This is an experimental alternate implementation of the Compose CLI (https://github.com/docker/compose)")
	return nil
}

// WithProject is an helper function to create a cli.Command action with a ProjectFactory.
func WithProject(factory ProjectFactory, action ProjectAction) func(context *cli.Context) {
	return func(context *cli.Context) {
		p, err := factory.Create(context)
		if err != nil {
			logrus.Fatalf("Failed to read project: %v", err)
		}
		action(p, context)
	}
}

// ProjectPs lists the containers.
func ProjectPs(p *project.Project, c *cli.Context) {
	allInfo := project.InfoSet{}
	for name := range p.Configs {
		service, err := p.CreateService(name)
		if err != nil {
			logrus.Fatal(err)
		}

		info, err := service.Info()
		if err != nil {
			logrus.Fatal(err)
		}

		allInfo = append(allInfo, info...)
	}

	os.Stdout.WriteString(allInfo.String())
}

// ProjectPort prints the public port for a port binding.
func ProjectPort(p *project.Project, c *cli.Context) {
	if len(c.Args()) != 2 {
		logrus.Fatalf("Please pass arguments in the form: SERVICE PORT")
	}

	index := c.Int("index")
	protocol := c.String("protocol")

	service, err := p.CreateService(c.Args()[0])
	if err != nil {
		logrus.Fatal(err)
	}

	containers, err := service.Containers()
	if err != nil {
		logrus.Fatal(err)
	}

	if index < 1 || index > len(containers) {
		logrus.Fatalf("Invalid index %d", index)
	}

	output, err := containers[index-1].Port(fmt.Sprintf("%s/%s", c.Args()[1], protocol))
	if err != nil {
		logrus.Fatal(err)
	}
	fmt.Println(output)
}

// ProjectDown brings all services down.
func ProjectDown(p *project.Project, c *cli.Context) {
	err := p.Down(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectBuild builds or rebuilds services.
func ProjectBuild(p *project.Project, c *cli.Context) {
	err := p.Build(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectCreate creates all services but do not start them.
func ProjectCreate(p *project.Project, c *cli.Context) {
	err := p.Create(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectUp brings all services up.
func ProjectUp(p *project.Project, c *cli.Context) {
	err := p.Up(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}

	if !c.Bool("d") {
		wait()
	}
}

// ProjectStart starts services.
func ProjectStart(p *project.Project, c *cli.Context) {
	err := p.Start(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectRestart restarts services.
func ProjectRestart(p *project.Project, c *cli.Context) {
	err := p.Restart(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectLog gets services logs.
func ProjectLog(p *project.Project, c *cli.Context) {
	err := p.Log(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
	wait()
}

// ProjectPull pulls images for services.
func ProjectPull(p *project.Project, c *cli.Context) {
	err := p.Pull(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectDelete delete services.
func ProjectDelete(p *project.Project, c *cli.Context) {
	if !c.Bool("force") && len(c.Args()) == 0 {
		logrus.Fatal("Will not remove all services with out --force")
	}
	err := p.Delete(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectKill forces stop service containers.
func ProjectKill(p *project.Project, c *cli.Context) {
	err := p.Kill(c.Args()...)
	if err != nil {
		logrus.Fatal(err)
	}
}

// ProjectScale scales services.
func ProjectScale(p *project.Project, c *cli.Context) {
	// This code is a bit verbose but I wanted to parse everything up front
	order := make([]string, 0, 0)
	serviceScale := make(map[string]int)
	services := make(map[string]project.Service)

	for _, arg := range c.Args() {
		kv := strings.SplitN(arg, "=", 2)
		if len(kv) != 2 {
			logrus.Fatalf("Invalid scale parameter: %s", arg)
		}

		name := kv[0]

		count, err := strconv.Atoi(kv[1])
		if err != nil {
			logrus.Fatalf("Invalid scale parameter: %v", err)
		}

		if _, ok := p.Configs[name]; !ok {
			logrus.Fatalf("%s is not defined in the template", name)
		}

		service, err := p.CreateService(name)
		if err != nil {
			logrus.Fatalf("Failed to lookup service: %s: %v", service, err)
		}

		order = append(order, name)
		serviceScale[name] = count
		services[name] = service
	}

	for _, name := range order {
		scale := serviceScale[name]
		logrus.Infof("Setting scale %s=%d...", name, scale)
		err := services[name].Scale(scale)
		if err != nil {
			logrus.Fatalf("Failed to set the scale %s=%d: %v", name, scale, err)
		}
	}
}

func wait() {
	<-make(chan interface{})
}
<|endoftext|>