<commit_before>package main

// pcstat.go - page cache stat
// uses the mincore(2) syscall to find out which pages (almost always 4k)
// of a file are currently cached in memory
//
// Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
// License: Apache 2.0

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"strings"
	"syscall"
	"unsafe"
)

// pcStat: page cache status
// Bytes: size of the file (from os.File.Stat())
// Pages: array of booleans: true if cached, false otherwise
type pcStat struct {
	Name     string `json:"filename"` // file name as specified on command line
	Size     int64  `json:"size"`     // file size in bytes
	Pages    int    `json:"pages"`    // total memory pages
	Cached   int    `json:"cached"`   // number of pages that are cached
	Uncached int    `json:"uncached"` // number of pages that are not cached
	PPStat   []bool `json:"status"`   // per-page status, true if cached, false otherwise
}

type pcStatList []pcStat

var (
	terseFlag, nohdrFlag, jsonFlag, ppsFlag, bnameFlag bool
)

func init() {
	// TODO: error on useless/broken combinations
	flag.BoolVar(&terseFlag, "terse", false, "show terse output")
	flag.BoolVar(&nohdrFlag, "nohdr", false, "omit the header from terse & text output")
	flag.BoolVar(&jsonFlag, "json", false, "return data in JSON format")
	flag.BoolVar(&ppsFlag, "pps", false, "include the per-page status in JSON output")
	flag.BoolVar(&bnameFlag, "bname", false, "convert paths to basename to narrow the output")
}

func main() {
	flag.Parse()

	// all non-flag arguments are considered to be filenames
	// this works well with shell globbing
	// file order is preserved throughout this program
	stats := make(pcStatList, len(flag.Args()))

	for i, fname := range flag.Args() {
		stats[i] = getMincore(fname)
	}

	if jsonFlag {
		stats.formatJson()
	} else if terseFlag {
		stats.formatTerse()
	} else {
		stats.formatText()
	}
}

func (stats pcStatList) formatText() {
	// find the longest filename in the data for calculating whitespace padding
	maxName := 8
	for _, pcs := range stats {
		if len(pcs.Name) > maxName {
			maxName = len(pcs.Name)
		}
	}

	// create horizontal grid line
	pad := strings.Repeat("-", maxName+2)
	hr := fmt.Sprintf("|%s+----------------+------------+-----------+---------|", pad)

	fmt.Println(hr)

	// -nohdr may be chosen to save 2 lines of precious vertical space
	if !nohdrFlag {
		pad = strings.Repeat(" ", maxName-4)
		fmt.Printf("| Name%s | Size           | Pages      | Cached    | Percent |\n", pad)
		fmt.Println(hr)
	}

	for _, pcs := range stats {
		// convert to float for the occasional sparsely-cached file
		// see the README.md for how to produce one
		percent := (float64(pcs.Cached) / float64(pcs.Pages)) * 100.00
		pad = strings.Repeat(" ", maxName-len(pcs.Name))

		// %07.3f was chosen to make it easy to scan the percentages vertically
		// I tried a few different formats only this one kept the decimals aligned
		fmt.Printf("| %s%s | %-15d| %-11d| %-10d| %07.3f |\n",
			pcs.Name, pad, pcs.Size, pcs.Pages, pcs.Cached, percent)
	}

	fmt.Println(hr)
}

func (stats pcStatList) formatTerse() {
	if !nohdrFlag {
		fmt.Println("name,size,pages,cached,percent")
	}
	for _, pcs := range stats {
		percent := (pcs.Cached / pcs.Pages) * 100
		fmt.Printf("%s,%d,%d,%d,%d\n", pcs.Name, pcs.Size, pcs.Pages, pcs.Cached, percent)
	}
}

func (stats pcStatList) formatJson() {
	b, err := json.Marshal(stats)
	if err != nil {
		log.Fatalf("JSON formatting failed: %s\n", err)
	}
	os.Stdout.Write(b)
	fmt.Println("")
}

func getMincore(fname string) pcStat {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatalf("Could not open file '%s' for read: %s\n", fname, err)
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		log.Fatalf("Could not stat file %s: %s\n", fname, err)
	}
	if fi.Size() == 0 {
		log.Fatalf("%s appears to be 0 bytes in length\n", fname)
	}

	// []byte slice
	mmap, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()), syscall.PROT_NONE, syscall.MAP_SHARED)
	if err != nil {
		log.Fatalf("Could not mmap file '%s': %s\n", fname, err)
	}
	// TODO: check for MAP_FAILED which is ((void *) -1)
	// but maybe unnecessary since it looks like errno is always set when MAP_FAILED

	// one byte per page, only LSB is used, remainder is reserved and clear
	vecsz := (fi.Size() + int64(os.Getpagesize()) - 1) / int64(os.Getpagesize())
	vec := make([]byte, vecsz)

	// get all of the arguments to the mincore syscall converted to uintptr
	mmap_ptr := uintptr(unsafe.Pointer(&mmap[0]))
	size_ptr := uintptr(fi.Size())
	vec_ptr := uintptr(unsafe.Pointer(&vec[0]))

	// use Go's ASM to submit directly to the kernel, no C wrapper needed
	// mincore(2): int mincore(void *addr, size_t length, unsigned char *vec);
	// 0 on success, takes the pointer to the mmap, a size, which is the
	// size that came from f.Stat(), and the vector, which is a pointer
	// to the memory behind an []byte
	// this writes a snapshot of the data into vec which a list of 8-bit flags
	// with the LSB set if the page in that position is currently in VFS cache
	ret, _, err := syscall.RawSyscall(syscall.SYS_MINCORE, mmap_ptr, size_ptr, vec_ptr)
	if ret != 0 {
		log.Fatalf("syscall SYS_MINCORE failed: %s", err)
	}
	defer syscall.Munmap(mmap)

	pcs := pcStat{fname, fi.Size(), int(vecsz), 0, 0, []bool{}}

	// only export the per-page cache mapping if it's explicitly enabled
	// an empty "status": [] field, but NBD.
	if ppsFlag {
		pcs.PPStat = make([]bool, vecsz)

		// there is no bitshift only bool
		for i, b := range vec {
			if b%2 == 1 {
				pcs.PPStat[i] = true
			} else {
				pcs.PPStat[i] = false
			}
		}

	}

	// convert long paths to their basename with the -bname flag
	// this overwrites the original filename in pcs but it doesn't matter since
	// it's not used to access the file again -- and should not be!
	if bnameFlag {
		pcs.Name = path.Base(fname)
	}

	for _, b := range vec {
		if b%2 == 1 {
			pcs.Cached++
		} else {
			pcs.Uncached++
		}
	}

	return pcs
}
<commit_msg>Use a proper Apache 2.0 license header.<commit_after>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * 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.
 *
 * pcstat.go - page cache stat
 *
 * uses the mincore(2) syscall to find out which pages (almost always 4k)
 * of a file are currently cached in memory
 *
 */

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"strings"
	"syscall"
	"unsafe"
)

// pcStat: page cache status
// Bytes: size of the file (from os.File.Stat())
// Pages: array of booleans: true if cached, false otherwise
type pcStat struct {
	Name     string `json:"filename"` // file name as specified on command line
	Size     int64  `json:"size"`     // file size in bytes
	Pages    int    `json:"pages"`    // total memory pages
	Cached   int    `json:"cached"`   // number of pages that are cached
	Uncached int    `json:"uncached"` // number of pages that are not cached
	PPStat   []bool `json:"status"`   // per-page status, true if cached, false otherwise
}

type pcStatList []pcStat

var (
	terseFlag, nohdrFlag, jsonFlag, ppsFlag, bnameFlag bool
)

func init() {
	// TODO: error on useless/broken combinations
	flag.BoolVar(&terseFlag, "terse", false, "show terse output")
	flag.BoolVar(&nohdrFlag, "nohdr", false, "omit the header from terse & text output")
	flag.BoolVar(&jsonFlag, "json", false, "return data in JSON format")
	flag.BoolVar(&ppsFlag, "pps", false, "include the per-page status in JSON output")
	flag.BoolVar(&bnameFlag, "bname", false, "convert paths to basename to narrow the output")
}

func main() {
	flag.Parse()

	// all non-flag arguments are considered to be filenames
	// this works well with shell globbing
	// file order is preserved throughout this program
	stats := make(pcStatList, len(flag.Args()))

	for i, fname := range flag.Args() {
		stats[i] = getMincore(fname)
	}

	if jsonFlag {
		stats.formatJson()
	} else if terseFlag {
		stats.formatTerse()
	} else {
		stats.formatText()
	}
}

func (stats pcStatList) formatText() {
	// find the longest filename in the data for calculating whitespace padding
	maxName := 8
	for _, pcs := range stats {
		if len(pcs.Name) > maxName {
			maxName = len(pcs.Name)
		}
	}

	// create horizontal grid line
	pad := strings.Repeat("-", maxName+2)
	hr := fmt.Sprintf("|%s+----------------+------------+-----------+---------|", pad)

	fmt.Println(hr)

	// -nohdr may be chosen to save 2 lines of precious vertical space
	if !nohdrFlag {
		pad = strings.Repeat(" ", maxName-4)
		fmt.Printf("| Name%s | Size           | Pages      | Cached    | Percent |\n", pad)
		fmt.Println(hr)
	}

	for _, pcs := range stats {
		// convert to float for the occasional sparsely-cached file
		// see the README.md for how to produce one
		percent := (float64(pcs.Cached) / float64(pcs.Pages)) * 100.00
		pad = strings.Repeat(" ", maxName-len(pcs.Name))

		// %07.3f was chosen to make it easy to scan the percentages vertically
		// I tried a few different formats only this one kept the decimals aligned
		fmt.Printf("| %s%s | %-15d| %-11d| %-10d| %07.3f |\n",
			pcs.Name, pad, pcs.Size, pcs.Pages, pcs.Cached, percent)
	}

	fmt.Println(hr)
}

func (stats pcStatList) formatTerse() {
	if !nohdrFlag {
		fmt.Println("name,size,pages,cached,percent")
	}
	for _, pcs := range stats {
		percent := (pcs.Cached / pcs.Pages) * 100
		fmt.Printf("%s,%d,%d,%d,%d\n", pcs.Name, pcs.Size, pcs.Pages, pcs.Cached, percent)
	}
}

func (stats pcStatList) formatJson() {
	b, err := json.Marshal(stats)
	if err != nil {
		log.Fatalf("JSON formatting failed: %s\n", err)
	}
	os.Stdout.Write(b)
	fmt.Println("")
}

func getMincore(fname string) pcStat {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatalf("Could not open file '%s' for read: %s\n", fname, err)
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		log.Fatalf("Could not stat file %s: %s\n", fname, err)
	}
	if fi.Size() == 0 {
		log.Fatalf("%s appears to be 0 bytes in length\n", fname)
	}

	// []byte slice
	mmap, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()), syscall.PROT_NONE, syscall.MAP_SHARED)
	if err != nil {
		log.Fatalf("Could not mmap file '%s': %s\n", fname, err)
	}
	// TODO: check for MAP_FAILED which is ((void *) -1)
	// but maybe unnecessary since it looks like errno is always set when MAP_FAILED

	// one byte per page, only LSB is used, remainder is reserved and clear
	vecsz := (fi.Size() + int64(os.Getpagesize()) - 1) / int64(os.Getpagesize())
	vec := make([]byte, vecsz)

	// get all of the arguments to the mincore syscall converted to uintptr
	mmap_ptr := uintptr(unsafe.Pointer(&mmap[0]))
	size_ptr := uintptr(fi.Size())
	vec_ptr := uintptr(unsafe.Pointer(&vec[0]))

	// use Go's ASM to submit directly to the kernel, no C wrapper needed
	// mincore(2): int mincore(void *addr, size_t length, unsigned char *vec);
	// 0 on success, takes the pointer to the mmap, a size, which is the
	// size that came from f.Stat(), and the vector, which is a pointer
	// to the memory behind an []byte
	// this writes a snapshot of the data into vec which a list of 8-bit flags
	// with the LSB set if the page in that position is currently in VFS cache
	ret, _, err := syscall.RawSyscall(syscall.SYS_MINCORE, mmap_ptr, size_ptr, vec_ptr)
	if ret != 0 {
		log.Fatalf("syscall SYS_MINCORE failed: %s", err)
	}
	defer syscall.Munmap(mmap)

	pcs := pcStat{fname, fi.Size(), int(vecsz), 0, 0, []bool{}}

	// only export the per-page cache mapping if it's explicitly enabled
	// an empty "status": [] field, but NBD.
	if ppsFlag {
		pcs.PPStat = make([]bool, vecsz)

		// there is no bitshift only bool
		for i, b := range vec {
			if b%2 == 1 {
				pcs.PPStat[i] = true
			} else {
				pcs.PPStat[i] = false
			}
		}

	}

	// convert long paths to their basename with the -bname flag
	// this overwrites the original filename in pcs but it doesn't matter since
	// it's not used to access the file again -- and should not be!
	if bnameFlag {
		pcs.Name = path.Base(fname)
	}

	for _, b := range vec {
		if b%2 == 1 {
			pcs.Cached++
		} else {
			pcs.Uncached++
		}
	}

	return pcs
}
<|endoftext|>


<commit_before>// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

// This module is a Table Writer  API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems

package tablewriter

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"testing"
)

func ExampleShort() {

	data := [][]string{
		[]string{"A", "The Good", "500"},
		[]string{"B", "The Very very Bad Man", "288"},
		[]string{"C", "The Ugly", "120"},
		[]string{"D", "The Gopher", "800"},
	}

	table := NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Sign", "Rating"})

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

}

func ExampleLong() {

	data := [][]string{
		[]string{"Learn East has computers with adapted keyboards with enlarged print etc", "  Some Data  ", " Another Data"},
		[]string{"Instead of lining up the letters all ", "the way across, he splits the keyboard in two", "Like most ergonomic keyboards", "See Data"},
	}

	table := NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Sign", "Rating"})
	table.SetCenterSeparator("*")
	table.SetRowSeparator("=")

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

}

func ExampleCSV() {
	table, _ := NewCSV(os.Stdout, "test.csv", true)
	table.SetCenterSeparator("*")
	table.SetRowSeparator("=")

	table.Render()
}

func TestCSVInfo(t *testing.T) {
	table, err := NewCSV(os.Stdout, "test_info.csv", true)
	if err != nil {
		t.Error(err)
		return
	}
	table.SetAlignment(ALIGN_LEFT)
	table.SetBorder(false)
	table.Render()
}

func TestCSVSeparator(t *testing.T) {
	table, err := NewCSV(os.Stdout, "test.csv", true)
	if err != nil {
		t.Error(err)
		return
	}
	table.SetRowLine(true)
	table.SetCenterSeparator("*")
	table.SetColumnSeparator("‡")
	table.SetRowSeparator("-")
	table.SetAlignment(ALIGN_LEFT)
	table.Render()
}

func TestBorder(t *testing.T) {
	data := [][]string{
		[]string{"1/1/2014", "Domain name", "2233", "$10.98"},
		[]string{"1/1/2014", "January Hosting", "2233", "$54.95"},
		[]string{"1/4/2014", "February Hosting", "2233", "$51.00"},
		[]string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"},
	}

	table := NewWriter(os.Stdout)
	table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
	table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer
	table.SetBorder(false)                                // Set Border to false
	table.AppendBulk(data)                                // Add Bulk Data
	table.Render()
}

func TestPrintHeading(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.printHeading()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("header rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintHeadingWithoutAutoFormat(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.SetAutoFormatHeaders(false)
	table.printHeading()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("header rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintFooter(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.SetFooter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.printFooter()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("footer rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintFooterWithoutAutoFormat(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetAutoFormatHeaders(false)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.SetFooter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.printFooter()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("footer rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintLine(t *testing.T) {
	header := make([]string, 12)
	val := " "
	want := ""
	for i := range header {
		header[i] = val
		want = fmt.Sprintf("%s+-%s-", want, strings.Replace(val, " ", "-", -1))
		val = val + " "
	}
	want = want + "+"
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader(header)
	table.printLine(false)
	got := buf.String()
	if got != want {
		t.Errorf("line rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestAnsiStrip(t *testing.T) {
	header := make([]string, 12)
	val := " "
	want := ""
	for i := range header {
		header[i] = "\033[43;30m" + val + "\033[00m"
		want = fmt.Sprintf("%s+-%s-", want, strings.Replace(val, " ", "-", -1))
		val = val + " "
	}
	want = want + "+"
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader(header)
	table.printLine(false)
	got := buf.String()
	if got != want {
		t.Errorf("line rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func NewCustomizedTable(out io.Writer) *Table {
	table := NewWriter(out)
	table.SetCenterSeparator("")
	table.SetColumnSeparator("")
	table.SetRowSeparator("")
	table.SetBorder(false)
	table.SetAlignment(ALIGN_LEFT)
	table.SetHeader([]string{})
	return table
}

func TestSubclass(t *testing.T) {
	buf := new(bytes.Buffer)
	table := NewCustomizedTable(buf)

	data := [][]string{
		[]string{"A", "The Good", "500"},
		[]string{"B", "The Very very Bad Man", "288"},
		[]string{"C", "The Ugly", "120"},
		[]string{"D", "The Gopher", "800"},
	}

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

	output := string(buf.Bytes())
	want := `  A  The Good               500
  B  The Very very Bad Man  288
  C  The Ugly               120
  D  The Gopher             800
`
	if output != want {
		t.Error(fmt.Sprintf("Unexpected output '%v' != '%v'", output, want))
	}
}
<commit_msg>Test SetAutoWrapText<commit_after>// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

// This module is a Table Writer  API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems

package tablewriter

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"testing"
)

func ExampleShort() {

	data := [][]string{
		[]string{"A", "The Good", "500"},
		[]string{"B", "The Very very Bad Man", "288"},
		[]string{"C", "The Ugly", "120"},
		[]string{"D", "The Gopher", "800"},
	}

	table := NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Sign", "Rating"})

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

}

func ExampleLong() {

	data := [][]string{
		[]string{"Learn East has computers with adapted keyboards with enlarged print etc", "  Some Data  ", " Another Data"},
		[]string{"Instead of lining up the letters all ", "the way across, he splits the keyboard in two", "Like most ergonomic keyboards", "See Data"},
	}

	table := NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Sign", "Rating"})
	table.SetCenterSeparator("*")
	table.SetRowSeparator("=")

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

}

func ExampleCSV() {
	table, _ := NewCSV(os.Stdout, "test.csv", true)
	table.SetCenterSeparator("*")
	table.SetRowSeparator("=")

	table.Render()
}

func TestCSVInfo(t *testing.T) {
	table, err := NewCSV(os.Stdout, "test_info.csv", true)
	if err != nil {
		t.Error(err)
		return
	}
	table.SetAlignment(ALIGN_LEFT)
	table.SetBorder(false)
	table.Render()
}

func TestCSVSeparator(t *testing.T) {
	table, err := NewCSV(os.Stdout, "test.csv", true)
	if err != nil {
		t.Error(err)
		return
	}
	table.SetRowLine(true)
	table.SetCenterSeparator("*")
	table.SetColumnSeparator("‡")
	table.SetRowSeparator("-")
	table.SetAlignment(ALIGN_LEFT)
	table.Render()
}

func TestBorder(t *testing.T) {
	data := [][]string{
		[]string{"1/1/2014", "Domain name", "2233", "$10.98"},
		[]string{"1/1/2014", "January Hosting", "2233", "$54.95"},
		[]string{"1/4/2014", "February Hosting", "2233", "$51.00"},
		[]string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"},
	}

	table := NewWriter(os.Stdout)
	table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
	table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer
	table.SetBorder(false)                                // Set Border to false
	table.AppendBulk(data)                                // Add Bulk Data
	table.Render()
}

func TestPrintHeading(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.printHeading()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("header rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintHeadingWithoutAutoFormat(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.SetAutoFormatHeaders(false)
	table.printHeading()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("header rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintFooter(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.SetFooter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.printFooter()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("footer rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintFooterWithoutAutoFormat(t *testing.T) {
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetAutoFormatHeaders(false)
	table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.SetFooter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"})
	table.printFooter()
	want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c |
+---+---+---+---+---+---+---+---+---+---+---+---+
`
	got := buf.String()
	if got != want {
		t.Errorf("footer rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintTableWithAndWithoutAutoWrap(t *testing.T) {
	var buf bytes.Buffer
	var multiline = `A multiline
string with some lines being really long.`

	with := NewWriter(&buf)
	with.Append([]string{multiline})
	with.Render()
	want := `+--------------------------------+
| A multiline string with some   |
| lines being really long.       |
+--------------------------------+
`
	got := buf.String()
	if got != want {
		t.Errorf("multiline text rendering with wrapping failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}

	buf.Truncate(0)
	without := NewWriter(&buf)
	without.SetAutoWrapText(false)
	without.Append([]string{multiline})
	without.Render()
	want = `+-------------------------------------------+
| A multiline                               |
| string with some lines being really long. |
+-------------------------------------------+
`
	got = buf.String()
	if got != want {
		t.Errorf("multiline text rendering without wrapping rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestPrintLine(t *testing.T) {
	header := make([]string, 12)
	val := " "
	want := ""
	for i := range header {
		header[i] = val
		want = fmt.Sprintf("%s+-%s-", want, strings.Replace(val, " ", "-", -1))
		val = val + " "
	}
	want = want + "+"
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader(header)
	table.printLine(false)
	got := buf.String()
	if got != want {
		t.Errorf("line rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func TestAnsiStrip(t *testing.T) {
	header := make([]string, 12)
	val := " "
	want := ""
	for i := range header {
		header[i] = "\033[43;30m" + val + "\033[00m"
		want = fmt.Sprintf("%s+-%s-", want, strings.Replace(val, " ", "-", -1))
		val = val + " "
	}
	want = want + "+"
	var buf bytes.Buffer
	table := NewWriter(&buf)
	table.SetHeader(header)
	table.printLine(false)
	got := buf.String()
	if got != want {
		t.Errorf("line rendering failed\ngot:\n%s\nwant:\n%s\n", got, want)
	}
}

func NewCustomizedTable(out io.Writer) *Table {
	table := NewWriter(out)
	table.SetCenterSeparator("")
	table.SetColumnSeparator("")
	table.SetRowSeparator("")
	table.SetBorder(false)
	table.SetAlignment(ALIGN_LEFT)
	table.SetHeader([]string{})
	return table
}

func TestSubclass(t *testing.T) {
	buf := new(bytes.Buffer)
	table := NewCustomizedTable(buf)

	data := [][]string{
		[]string{"A", "The Good", "500"},
		[]string{"B", "The Very very Bad Man", "288"},
		[]string{"C", "The Ugly", "120"},
		[]string{"D", "The Gopher", "800"},
	}

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

	output := string(buf.Bytes())
	want := `  A  The Good               500
  B  The Very very Bad Man  288
  C  The Ugly               120
  D  The Gopher             800
`
	if output != want {
		t.Error(fmt.Sprintf("Unexpected output '%v' != '%v'", output, want))
	}
}
<|endoftext|>


<commit_before>/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

    * Neither the name of "The Computer Language Benchmarks Game" nor the
    name of "The Computer Language Shootout Benchmarks" nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

/* The Computer Language Benchmarks Game
 * http://shootout.alioth.debian.org/
 *
 * contributed by The Go Authors.
 * Based on C program by Joern Inge Vestgaarden
 * and Jorge Peixoto de Morais Neto.
 */

package main

import (
	"bufio";
	"flag";
	"os";
	"strings";
)

var out *bufio.Writer

var n = flag.Int("n", 1000, "length of result")

const WIDTH = 60	// Fold lines after WIDTH bytes

func min(a, b int) int {
	if a < b {
		return a
	}
	return b;
}

type AminoAcid struct {
	p	float;
	c	byte;
}

var lastrandom uint32 = 42

// Random number between 0.0 and 1.0
func myrandom() float {
	const (
		IM	= 139968;
		IA	= 3877;
		IC	= 29573;
	)
	lastrandom = (lastrandom*IA + IC) % IM;
	// Integer to float conversions are faster if the integer is signed.
	return float(int32(lastrandom)) / IM;
}

func AccumulateProbabilities(genelist []AminoAcid) {
	for i := 1; i < len(genelist); i++ {
		genelist[i].p += genelist[i-1].p
	}
}

// RepeatFasta prints the characters of the byte slice s. When it
// reaches the end of the slice, it goes back to the beginning.
// It stops after generating count characters.
// After each WIDTH characters it prints a newline.
// It assumes that WIDTH <= len(s) + 1.
func RepeatFasta(s []byte, count int) {
	pos := 0;
	s2 := make([]byte, len(s)+WIDTH);
	copy(s2, s);
	copy(s2[len(s):], s);
	for count > 0 {
		line := min(WIDTH, count);
		out.Write(s2[pos : pos+line]);
		out.WriteByte('\n');
		pos += line;
		if pos >= len(s) {
			pos -= len(s)
		}
		count -= line;
	}
}

// Each element of genelist is a struct with a character and
// a floating point number p between 0 and 1.
// RandomFasta generates a random float r and
// finds the first element such that p >= r.
// This is a weighted random selection.
// RandomFasta then prints the character of the array element.
// This sequence is repeated count times.
// Between each WIDTH consecutive characters, the function prints a newline.
func RandomFasta(genelist []AminoAcid, count int) {
	buf := make([]byte, WIDTH+1);
	for count > 0 {
		line := min(WIDTH, count);
		for pos := 0; pos < line; pos++ {
			r := myrandom();
			var i int;
			for i = 0; genelist[i].p < r; i++ {
			}
			buf[pos] = genelist[i].c;
		}
		buf[line] = '\n';
		out.Write(buf[0 : line+1]);
		count -= line;
	}
}

func main() {
	out = bufio.NewWriter(os.Stdout);
	defer out.Flush();

	flag.Parse();

	iub := []AminoAcid{
		AminoAcid{0.27, 'a'},
		AminoAcid{0.12, 'c'},
		AminoAcid{0.12, 'g'},
		AminoAcid{0.27, 't'},
		AminoAcid{0.02, 'B'},
		AminoAcid{0.02, 'D'},
		AminoAcid{0.02, 'H'},
		AminoAcid{0.02, 'K'},
		AminoAcid{0.02, 'M'},
		AminoAcid{0.02, 'N'},
		AminoAcid{0.02, 'R'},
		AminoAcid{0.02, 'S'},
		AminoAcid{0.02, 'V'},
		AminoAcid{0.02, 'W'},
		AminoAcid{0.02, 'Y'},
	};

	homosapiens := []AminoAcid{
		AminoAcid{0.3029549426680, 'a'},
		AminoAcid{0.1979883004921, 'c'},
		AminoAcid{0.1975473066391, 'g'},
		AminoAcid{0.3015094502008, 't'},
	};

	AccumulateProbabilities(iub);
	AccumulateProbabilities(homosapiens);

	alu := strings.Bytes(
		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"
			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"
			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"
			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"
			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"
			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"
			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA");

	out.WriteString(">ONE Homo sapiens alu\n");
	RepeatFasta(alu, 2**n);
	out.WriteString(">TWO IUB ambiguity codes\n");
	RandomFasta(iub, 3**n);
	out.WriteString(">THREE Homo sapiens frequency\n");
	RandomFasta(homosapiens, 5**n);
}
<commit_msg>test/bench: faster fasta (mostly due to bufio fix)<commit_after>/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

    * Neither the name of "The Computer Language Benchmarks Game" nor the
    name of "The Computer Language Shootout Benchmarks" nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

/* The Computer Language Benchmarks Game
 * http://shootout.alioth.debian.org/
 *
 * contributed by The Go Authors.
 * Based on C program by Joern Inge Vestgaarden
 * and Jorge Peixoto de Morais Neto.
 */

package main

import (
	"bufio";
	"flag";
	"os";
	"strings";
)

var out *bufio.Writer

var n = flag.Int("n", 1000, "length of result")

const WIDTH = 60	// Fold lines after WIDTH bytes

func min(a, b int) int {
	if a < b {
		return a
	}
	return b;
}

type AminoAcid struct {
	p	float;
	c	byte;
}

func AccumulateProbabilities(genelist []AminoAcid) {
	for i := 1; i < len(genelist); i++ {
		genelist[i].p += genelist[i-1].p
	}
}

// RepeatFasta prints the characters of the byte slice s. When it
// reaches the end of the slice, it goes back to the beginning.
// It stops after generating count characters.
// After each WIDTH characters it prints a newline.
// It assumes that WIDTH <= len(s) + 1.
func RepeatFasta(s []byte, count int) {
	pos := 0;
	s2 := make([]byte, len(s)+WIDTH);
	copy(s2, s);
	copy(s2[len(s):], s);
	for count > 0 {
		line := min(WIDTH, count);
		out.Write(s2[pos : pos+line]);
		out.WriteByte('\n');
		pos += line;
		if pos >= len(s) {
			pos -= len(s)
		}
		count -= line;
	}
}

var lastrandom uint32 = 42

const (
	IM	= 139968;
	IA	= 3877;
	IC	= 29573;
)

// Each element of genelist is a struct with a character and
// a floating point number p between 0 and 1.
// RandomFasta generates a random float r and
// finds the first element such that p >= r.
// This is a weighted random selection.
// RandomFasta then prints the character of the array element.
// This sequence is repeated count times.
// Between each WIDTH consecutive characters, the function prints a newline.
func RandomFasta(genelist []AminoAcid, count int) {
	buf := make([]byte, WIDTH+1);
	for count > 0 {
		line := min(WIDTH, count);
		for pos := 0; pos < line; pos++ {
			lastrandom = (lastrandom*IA + IC) % IM;
			// Integer to float conversions are faster if the integer is signed.
			r := float(int32(lastrandom)) / IM;
			for _, v := range genelist {
				if v.p >= r {
					buf[pos] = v.c;
					break;
				}
			}
		}
		buf[line] = '\n';
		out.Write(buf[0 : line+1]);
		count -= line;
	}
}

func main() {
	out = bufio.NewWriter(os.Stdout);
	defer out.Flush();

	flag.Parse();

	iub := []AminoAcid{
		AminoAcid{0.27, 'a'},
		AminoAcid{0.12, 'c'},
		AminoAcid{0.12, 'g'},
		AminoAcid{0.27, 't'},
		AminoAcid{0.02, 'B'},
		AminoAcid{0.02, 'D'},
		AminoAcid{0.02, 'H'},
		AminoAcid{0.02, 'K'},
		AminoAcid{0.02, 'M'},
		AminoAcid{0.02, 'N'},
		AminoAcid{0.02, 'R'},
		AminoAcid{0.02, 'S'},
		AminoAcid{0.02, 'V'},
		AminoAcid{0.02, 'W'},
		AminoAcid{0.02, 'Y'},
	};

	homosapiens := []AminoAcid{
		AminoAcid{0.3029549426680, 'a'},
		AminoAcid{0.1979883004921, 'c'},
		AminoAcid{0.1975473066391, 'g'},
		AminoAcid{0.3015094502008, 't'},
	};

	AccumulateProbabilities(iub);
	AccumulateProbabilities(homosapiens);

	alu := strings.Bytes(
		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"
			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"
			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"
			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"
			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"
			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"
			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA");

	out.WriteString(">ONE Homo sapiens alu\n");
	RepeatFasta(alu, 2**n);
	out.WriteString(">TWO IUB ambiguity codes\n");
	RandomFasta(iub, 3**n);
	out.WriteString(">THREE Homo sapiens frequency\n");
	RandomFasta(homosapiens, 5**n);
}
<|endoftext|>


<commit_before>// errchk $G $D/$F.go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	OS "os"  // should require semicolon here; this is no different from other decls
	IO "io"
)

func main() {
}
<commit_msg>Add ERROR comment for errmsg to look for.<commit_after>// errchk $G $D/$F.go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	OS "os"  // should require semicolon here; this is no different from other decls
	IO "io"  // ERROR "missing"
)

func main() {
}
<|endoftext|>


<commit_before>// errchk $G $D/$F.go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main
func main() {
        var x int64 = 0;
        println(x != nil);	// ERROR ".*"
        println(0 != nil);	// ERROR ".*"
}
<commit_msg>The DejaGNU testsuite harness used by the gccgo testsuite is broken if you give it something which matches everything--the .* swallows all the error messages.  Recognize some reasonable error text directly.<commit_after>// errchk $G $D/$F.go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main
func main() {
        var x int64 = 0;
        println(x != nil);	// ERROR "illegal|incompatible"
        println(0 != nil);	// ERROR "illegal|incompatible"
}
<|endoftext|>


<commit_before>package database

import (
	"database/sql"
	"fmt"
	log "github.com/Sirupsen/logrus"

	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"github.com/pagarme/teleport/action"
	"github.com/pagarme/teleport/asset"
	"github.com/pagarme/teleport/config"
)

// Database definition
type Database struct {
	Name    string
	Config  config.Database
	Schemas map[string]*Schema
	Db      *sqlx.DB
}

func New(dbconf config.Database) *Database {
	return &Database{
		Name:    dbconf.Name,
		Config:  dbconf,
		Schemas: make(map[string]*Schema),
	}
}

func (db *Database) ConnectionString() string {
	s := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d",
		db.Config.Hostname,
		db.Config.Username,
		db.Config.Password,
		db.Config.Database,
		db.Config.Port,
	)
	for k, v := range db.Config.Options {
		s += " " + k + "=" + v
	}
	return s
}

// Open connection with database and setup internal tables
func (db *Database) Start() error {
	var err error

	db.Db, err = sqlx.Connect("postgres", db.ConnectionString())
	db.Db.SetMaxOpenConns(5)

	if err != nil {
		return err
	}

	err = db.setupTables()

	if err != nil {
		return err
	}

	err = db.RefreshSchema()

	if err != nil {
		return err
	}

	return nil
}

func (db *Database) NewTransaction() *sqlx.Tx {
	return db.Db.MustBegin()
}

// Install triggers on a source table
func (db *Database) InstallTriggers(targetExpression string) error {
	err := db.installDDLTriggers()

	if err != nil {
		return err
	}

	// Install triggers for each table
	for _, schema := range db.Schemas {
		for _, class := range schema.Tables {
			// If class is not a table, continue...
			if class.RelationKind != "r" {
				continue
			}

			if action.IsInTargetExpression(&targetExpression, &schema.Name, &class.RelationName) {
				class.InstallTriggers()
				//
				// if err != nil {
				// 	return err
				// }
			}
		}
	}

	return nil
}

// Install triggers in schema
func (db *Database) installDDLTriggers() error {
	rows, err := db.runQueryFromFile("data/sql/source_trigger.sql")

	if err == nil {
		log.Infof("Installed triggers on database")
	} else {
		log.Warnf("Failed to install triggers on database: %v", err)
	}

	rows.Close()
	return err
}

// Setup internal tables using setup script
func (db *Database) setupTables() error {
	rows, err := db.runQueryFromFile("data/sql/setup.sql")

	if err != nil {
		return err
	}

	rows.Close()
	return nil
}

// Run query on database
func (db *Database) runQuery(query string, args ...interface{}) (*sql.Rows, error) {
	return db.Db.Query(query, args...)
}

func (db *Database) selectObjs(v interface{}, query string, args ...interface{}) error {
	return db.Db.Select(v, query, args...)
}

// Open file and run query
func (db *Database) runQueryFromFile(file string) (*sql.Rows, error) {
	// Read file
	content, err := asset.Asset(file)

	if err != nil {
		return nil, err
	}

	return db.runQuery(string(content))
}
<commit_msg>Rename function<commit_after>package database

import (
	"database/sql"
	"fmt"
	log "github.com/Sirupsen/logrus"

	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"github.com/pagarme/teleport/action"
	"github.com/pagarme/teleport/asset"
	"github.com/pagarme/teleport/config"
)

// Database definition
type Database struct {
	Name    string
	Config  config.Database
	Schemas map[string]*Schema
	Db      *sqlx.DB
}

func New(dbconf config.Database) *Database {
	return &Database{
		Name:    dbconf.Name,
		Config:  dbconf,
		Schemas: make(map[string]*Schema),
	}
}

func (db *Database) ConnectionString() string {
	s := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d",
		db.Config.Hostname,
		db.Config.Username,
		db.Config.Password,
		db.Config.Database,
		db.Config.Port,
	)
	for k, v := range db.Config.Options {
		s += " " + k + "=" + v
	}
	return s
}

// Open connection with database and setup internal tables
func (db *Database) Start() error {
	var err error

	db.Db, err = sqlx.Connect("postgres", db.ConnectionString())
	db.Db.SetMaxOpenConns(5)

	if err != nil {
		return err
	}

	err = db.setupTables()

	if err != nil {
		return err
	}

	err = db.RefreshSchema()

	if err != nil {
		return err
	}

	return nil
}

func (db *Database) NewTransaction() *sqlx.Tx {
	return db.Db.MustBegin()
}

// Install triggers on a source table
func (db *Database) InstallTriggers(targetExpression string) error {
	err := db.installLDDLWatcher()

	if err != nil {
		return err
	}

	// Install triggers for each table
	for _, schema := range db.Schemas {
		for _, class := range schema.Tables {
			// If class is not a table, continue...
			if class.RelationKind != "r" {
				continue
			}

			if action.IsInTargetExpression(&targetExpression, &schema.Name, &class.RelationName) {
				class.InstallTriggers()
				//
				// if err != nil {
				// 	return err
				// }
			}
		}
	}

	return nil
}

// Install source triggers using watcher
func (db *Database) installLDDLWatcher() error {
	rows, err := db.runQueryFromFile("data/sql/source_trigger.sql")

	if err == nil {
		log.Infof("Installed triggers on database")
	} else {
		log.Warnf("Failed to install triggers on database: %v", err)
	}

	rows.Close()
	return err
}

// Setup internal tables using setup script
func (db *Database) setupTables() error {
	rows, err := db.runQueryFromFile("data/sql/setup.sql")

	if err != nil {
		return err
	}

	rows.Close()
	return nil
}

// Run query on database
func (db *Database) runQuery(query string, args ...interface{}) (*sql.Rows, error) {
	return db.Db.Query(query, args...)
}

func (db *Database) selectObjs(v interface{}, query string, args ...interface{}) error {
	return db.Db.Select(v, query, args...)
}

// Open file and run query
func (db *Database) runQueryFromFile(file string) (*sql.Rows, error) {
	// Read file
	content, err := asset.Asset(file)

	if err != nil {
		return nil, err
	}

	return db.runQuery(string(content))
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"strconv"
	"strings"
)

// Config is user config for http traffics
type Config struct {
	level      string
	filterIP   string
	filterPort uint16
	host       string
	uri        string
	status     *IntSet
	force      bool
	pretty     bool
	output     string
}

// parse int set
func ParseIntSet(str string) (*IntSet, error) {
	if str == "" {
		return nil, errors.New("empty str")
	}
	var intSet IntSet
	for _, item := range strings.Split(str, ":") {
		var numbers = strings.Split(item, "-")
		if len(numbers) > 2 {
			return nil, errors.New("illegal range str: " + item)
		}
		if len(numbers) == 1 {
			start, err := strconv.Atoi(numbers[0])
			if err != nil {
				return nil, err
			}
			intSet.ranges = append(intSet.ranges, NewIntRange(start, start))
		} else if len(numbers) == 2 {
			start, err := strconv.Atoi(numbers[0])
			if err != nil {
				return nil, err
			}
			end, err := strconv.Atoi(numbers[1])
			if err != nil {
				return nil, err
			}
			intSet.ranges = append(intSet.ranges, NewIntRange(start, end))
		}
	}
	return &intSet, nil
}

// A set of int values
type IntSet struct {
	ranges []IntRange
}

// Create new IntSet
func NewIntSet(ranges ...IntRange) *IntSet {
	return &IntSet{
		ranges: ranges,
	}
}

// implement Stringer
func (s *IntSet) String() string {
	var sb strings.Builder
	for index, r := range s.ranges {
		if index > 0 {
			sb.WriteRune(':')
		}
		if r.Start == r.End {
			sb.WriteString(strconv.Itoa(r.Start))
		} else {
			sb.WriteString(strconv.Itoa(r.Start))
			sb.WriteRune('-')
			sb.WriteString(strconv.Itoa(r.End))
		}
	}
	return sb.String()
}

// If this set contains int value
func (s *IntSet) Contains(value int) bool {
	for _, r := range s.ranges {
		if r.Contains(value) {
			return true
		}
	}
	return false
}

// Range of int value
type IntRange struct {
	Start int // inclusive
	End   int // inclusive
}

// Create new int range
func NewIntRange(start int, end int) IntRange {
	return IntRange{
		Start: start,
		End:   end,
	}
}

// If this range contains the value
func (r *IntRange) Contains(value int) bool {
	return value >= r.Start && value <= r.End
}
<commit_msg>forgot config_struct.go<commit_after>package main

import (
	"errors"
	"strconv"
	"strings"
)

// Config is user config for http traffics
type Config struct {
	level      string
	filterIP   string
	filterPort uint16
	host       string
	uri        string
	status     *IntSet
	force      bool
	pretty     bool
	curl       bool
	output     string
}

// parse int set
func ParseIntSet(str string) (*IntSet, error) {
	if str == "" {
		return nil, errors.New("empty str")
	}
	var intSet IntSet
	for _, item := range strings.Split(str, ":") {
		var numbers = strings.Split(item, "-")
		if len(numbers) > 2 {
			return nil, errors.New("illegal range str: " + item)
		}
		if len(numbers) == 1 {
			start, err := strconv.Atoi(numbers[0])
			if err != nil {
				return nil, err
			}
			intSet.ranges = append(intSet.ranges, NewIntRange(start, start))
		} else if len(numbers) == 2 {
			start, err := strconv.Atoi(numbers[0])
			if err != nil {
				return nil, err
			}
			end, err := strconv.Atoi(numbers[1])
			if err != nil {
				return nil, err
			}
			intSet.ranges = append(intSet.ranges, NewIntRange(start, end))
		}
	}
	return &intSet, nil
}

// A set of int values
type IntSet struct {
	ranges []IntRange
}

// Create new IntSet
func NewIntSet(ranges ...IntRange) *IntSet {
	return &IntSet{
		ranges: ranges,
	}
}

// implement Stringer
func (s *IntSet) String() string {
	var sb strings.Builder
	for index, r := range s.ranges {
		if index > 0 {
			sb.WriteRune(':')
		}
		if r.Start == r.End {
			sb.WriteString(strconv.Itoa(r.Start))
		} else {
			sb.WriteString(strconv.Itoa(r.Start))
			sb.WriteRune('-')
			sb.WriteString(strconv.Itoa(r.End))
		}
	}
	return sb.String()
}

// If this set contains int value
func (s *IntSet) Contains(value int) bool {
	for _, r := range s.ranges {
		if r.Contains(value) {
			return true
		}
	}
	return false
}

// Range of int value
type IntRange struct {
	Start int // inclusive
	End   int // inclusive
}

// Create new int range
func NewIntRange(start int, end int) IntRange {
	return IntRange{
		Start: start,
		End:   end,
	}
}

// If this range contains the value
func (r *IntRange) Contains(value int) bool {
	return value >= r.Start && value <= r.End
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes 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 e2e

import (
	"fmt"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/fields"
	kubepod "k8s.io/kubernetes/pkg/kubelet/pod"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/util/wait"
	"k8s.io/kubernetes/test/e2e/framework"
	testutils "k8s.io/kubernetes/test/utils"

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

func isRestartNeverMirrorPod(p *api.Pod) bool {
	if !kubepod.IsMirrorPod(p) {
		return false
	}
	return p.Spec.RestartPolicy == api.RestartPolicyNever
}

func filterIrrelevantPods(pods []*api.Pod) []*api.Pod {
	var results []*api.Pod
	for _, p := range pods {
		if isRestartNeverMirrorPod(p) {
			// Mirror pods with restart policy == Never will not get
			// recreated if they are deleted after the pods have
			// terminated. For now, we discount such pods.
			// https://github.com/kubernetes/kubernetes/issues/34003
			continue
		}
		results = append(results, p)
	}
	return results
}

var _ = framework.KubeDescribe("Restart [Disruptive]", func() {
	f := framework.NewDefaultFramework("restart")
	var ps *testutils.PodStore

	BeforeEach(func() {
		// This test requires the ability to restart all nodes, so the provider
		// check must be identical to that call.
		framework.SkipUnlessProviderIs("gce", "gke")

		ps = testutils.NewPodStore(f.ClientSet, api.NamespaceSystem, labels.Everything(), fields.Everything())
	})

	AfterEach(func() {
		if ps != nil {
			ps.Stop()
		}
	})

	It("should restart all nodes and ensure all nodes and pods recover", func() {
		nn := framework.TestContext.CloudConfig.NumNodes

		By("ensuring all nodes are ready")
		nodeNamesBefore, err := framework.CheckNodesReady(f.ClientSet, framework.NodeReadyInitialTimeout, nn)
		Expect(err).NotTo(HaveOccurred())
		framework.Logf("Got the following nodes before restart: %v", nodeNamesBefore)

		By("ensuring all pods are running and ready")
		allPods := ps.List()
		pods := filterIrrelevantPods(allPods)

		podNamesBefore := make([]string, len(pods))
		for i, p := range pods {
			podNamesBefore[i] = p.ObjectMeta.Name
		}
		ns := api.NamespaceSystem
		if !framework.CheckPodsRunningReadyOrSucceeded(f.ClientSet, ns, podNamesBefore, framework.PodReadyBeforeTimeout) {
			framework.Failf("At least one pod wasn't running and ready or succeeded at test start.")
		}

		By("restarting all of the nodes")
		err = restartNodes(f, nodeNamesBefore)
		Expect(err).NotTo(HaveOccurred())

		By("ensuring all nodes are ready after the restart")
		nodeNamesAfter, err := framework.CheckNodesReady(f.ClientSet, framework.RestartNodeReadyAgainTimeout, nn)
		Expect(err).NotTo(HaveOccurred())
		framework.Logf("Got the following nodes after restart: %v", nodeNamesAfter)

		// Make sure that we have the same number of nodes. We're not checking
		// that the names match because that's implementation specific.
		By("ensuring the same number of nodes exist after the restart")
		if len(nodeNamesBefore) != len(nodeNamesAfter) {
			framework.Failf("Had %d nodes before nodes were restarted, but now only have %d",
				len(nodeNamesBefore), len(nodeNamesAfter))
		}

		// Make sure that we have the same number of pods. We're not checking
		// that the names match because they are recreated with different names
		// across node restarts.
		By("ensuring the same number of pods are running and ready after restart")
		podCheckStart := time.Now()
		podNamesAfter, err := waitForNPods(ps, len(podNamesBefore), framework.RestartPodReadyAgainTimeout)
		Expect(err).NotTo(HaveOccurred())
		remaining := framework.RestartPodReadyAgainTimeout - time.Since(podCheckStart)
		if !framework.CheckPodsRunningReadyOrSucceeded(f.ClientSet, ns, podNamesAfter, remaining) {
			framework.Failf("At least one pod wasn't running and ready after the restart.")
		}
	})
})

// waitForNPods tries to list pods using c until it finds expect of them,
// returning their names if it can do so before timeout.
func waitForNPods(ps *testutils.PodStore, expect int, timeout time.Duration) ([]string, error) {
	// Loop until we find expect pods or timeout is passed.
	var pods []*api.Pod
	var errLast error
	found := wait.Poll(framework.Poll, timeout, func() (bool, error) {
		allPods := ps.List()
		pods := filterIrrelevantPods(allPods)
		if len(pods) != expect {
			errLast = fmt.Errorf("expected to find %d pods but found only %d", expect, len(pods))
			framework.Logf("Error getting pods: %v", errLast)
			return false, nil
		}
		return true, nil
	}) == nil
	// Extract the names of all found pods.
	podNames := make([]string, len(pods))
	for i, p := range pods {
		podNames[i] = p.ObjectMeta.Name
	}
	if !found {
		return podNames, fmt.Errorf("couldn't find %d pods within %v; last error: %v",
			expect, timeout, errLast)
	}
	return podNames, nil
}

func restartNodes(f *framework.Framework, nodeNames []string) error {
	// List old boot IDs.
	oldBootIDs := make(map[string]string)
	for _, name := range nodeNames {
		node, err := f.ClientSet.Core().Nodes().Get(name)
		if err != nil {
			return fmt.Errorf("error getting node info before reboot: %s", err)
		}
		oldBootIDs[name] = node.Status.NodeInfo.BootID
	}
	// Reboot the nodes.
	args := []string{
		"compute",
		fmt.Sprintf("--project=%s", framework.TestContext.CloudConfig.ProjectID),
		"instances",
		"reset",
	}
	args = append(args, nodeNames...)
	args = append(args, fmt.Sprintf("--zone=%s", framework.TestContext.CloudConfig.Zone))
	stdout, stderr, err := framework.RunCmd("gcloud", args...)
	if err != nil {
		return fmt.Errorf("error restarting nodes: %s\nstdout: %s\nstderr: %s", err, stdout, stderr)
	}
	// Wait for their boot IDs to change.
	for _, name := range nodeNames {
		if err := wait.Poll(30*time.Second, 5*time.Minute, func() (bool, error) {
			node, err := f.ClientSet.Core().Nodes().Get(name)
			if err != nil {
				return false, fmt.Errorf("error getting node info after reboot: %s", err)
			}
			return node.Status.NodeInfo.BootID != oldBootIDs[name], nil
		}); err != nil {
			return fmt.Errorf("error waiting for node %s boot ID to change: %s", name, err)
		}
	}
	return nil
}
<commit_msg>Filter out non-RestartAlways mirror pod in restart test.<commit_after>/*
Copyright 2015 The Kubernetes 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 e2e

import (
	"fmt"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/fields"
	kubepod "k8s.io/kubernetes/pkg/kubelet/pod"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/util/wait"
	"k8s.io/kubernetes/test/e2e/framework"
	testutils "k8s.io/kubernetes/test/utils"

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

func isNotRestartAlwaysMirrorPod(p *api.Pod) bool {
	if !kubepod.IsMirrorPod(p) {
		return false
	}
	return p.Spec.RestartPolicy != api.RestartPolicyAlways
}

func filterIrrelevantPods(pods []*api.Pod) []*api.Pod {
	var results []*api.Pod
	for _, p := range pods {
		if isNotRestartAlwaysMirrorPod(p) {
			// Mirror pods with restart policy == Never will not get
			// recreated if they are deleted after the pods have
			// terminated. For now, we discount such pods.
			// https://github.com/kubernetes/kubernetes/issues/34003
			continue
		}
		results = append(results, p)
	}
	return results
}

var _ = framework.KubeDescribe("Restart [Disruptive]", func() {
	f := framework.NewDefaultFramework("restart")
	var ps *testutils.PodStore

	BeforeEach(func() {
		// This test requires the ability to restart all nodes, so the provider
		// check must be identical to that call.
		framework.SkipUnlessProviderIs("gce", "gke")

		ps = testutils.NewPodStore(f.ClientSet, api.NamespaceSystem, labels.Everything(), fields.Everything())
	})

	AfterEach(func() {
		if ps != nil {
			ps.Stop()
		}
	})

	It("should restart all nodes and ensure all nodes and pods recover", func() {
		nn := framework.TestContext.CloudConfig.NumNodes

		By("ensuring all nodes are ready")
		nodeNamesBefore, err := framework.CheckNodesReady(f.ClientSet, framework.NodeReadyInitialTimeout, nn)
		Expect(err).NotTo(HaveOccurred())
		framework.Logf("Got the following nodes before restart: %v", nodeNamesBefore)

		By("ensuring all pods are running and ready")
		allPods := ps.List()
		pods := filterIrrelevantPods(allPods)

		podNamesBefore := make([]string, len(pods))
		for i, p := range pods {
			podNamesBefore[i] = p.ObjectMeta.Name
		}
		ns := api.NamespaceSystem
		if !framework.CheckPodsRunningReadyOrSucceeded(f.ClientSet, ns, podNamesBefore, framework.PodReadyBeforeTimeout) {
			framework.Failf("At least one pod wasn't running and ready or succeeded at test start.")
		}

		By("restarting all of the nodes")
		err = restartNodes(f, nodeNamesBefore)
		Expect(err).NotTo(HaveOccurred())

		By("ensuring all nodes are ready after the restart")
		nodeNamesAfter, err := framework.CheckNodesReady(f.ClientSet, framework.RestartNodeReadyAgainTimeout, nn)
		Expect(err).NotTo(HaveOccurred())
		framework.Logf("Got the following nodes after restart: %v", nodeNamesAfter)

		// Make sure that we have the same number of nodes. We're not checking
		// that the names match because that's implementation specific.
		By("ensuring the same number of nodes exist after the restart")
		if len(nodeNamesBefore) != len(nodeNamesAfter) {
			framework.Failf("Had %d nodes before nodes were restarted, but now only have %d",
				len(nodeNamesBefore), len(nodeNamesAfter))
		}

		// Make sure that we have the same number of pods. We're not checking
		// that the names match because they are recreated with different names
		// across node restarts.
		By("ensuring the same number of pods are running and ready after restart")
		podCheckStart := time.Now()
		podNamesAfter, err := waitForNPods(ps, len(podNamesBefore), framework.RestartPodReadyAgainTimeout)
		Expect(err).NotTo(HaveOccurred())
		remaining := framework.RestartPodReadyAgainTimeout - time.Since(podCheckStart)
		if !framework.CheckPodsRunningReadyOrSucceeded(f.ClientSet, ns, podNamesAfter, remaining) {
			framework.Failf("At least one pod wasn't running and ready after the restart.")
		}
	})
})

// waitForNPods tries to list pods using c until it finds expect of them,
// returning their names if it can do so before timeout.
func waitForNPods(ps *testutils.PodStore, expect int, timeout time.Duration) ([]string, error) {
	// Loop until we find expect pods or timeout is passed.
	var pods []*api.Pod
	var errLast error
	found := wait.Poll(framework.Poll, timeout, func() (bool, error) {
		allPods := ps.List()
		pods := filterIrrelevantPods(allPods)
		if len(pods) != expect {
			errLast = fmt.Errorf("expected to find %d pods but found only %d", expect, len(pods))
			framework.Logf("Error getting pods: %v", errLast)
			return false, nil
		}
		return true, nil
	}) == nil
	// Extract the names of all found pods.
	podNames := make([]string, len(pods))
	for i, p := range pods {
		podNames[i] = p.ObjectMeta.Name
	}
	if !found {
		return podNames, fmt.Errorf("couldn't find %d pods within %v; last error: %v",
			expect, timeout, errLast)
	}
	return podNames, nil
}

func restartNodes(f *framework.Framework, nodeNames []string) error {
	// List old boot IDs.
	oldBootIDs := make(map[string]string)
	for _, name := range nodeNames {
		node, err := f.ClientSet.Core().Nodes().Get(name)
		if err != nil {
			return fmt.Errorf("error getting node info before reboot: %s", err)
		}
		oldBootIDs[name] = node.Status.NodeInfo.BootID
	}
	// Reboot the nodes.
	args := []string{
		"compute",
		fmt.Sprintf("--project=%s", framework.TestContext.CloudConfig.ProjectID),
		"instances",
		"reset",
	}
	args = append(args, nodeNames...)
	args = append(args, fmt.Sprintf("--zone=%s", framework.TestContext.CloudConfig.Zone))
	stdout, stderr, err := framework.RunCmd("gcloud", args...)
	if err != nil {
		return fmt.Errorf("error restarting nodes: %s\nstdout: %s\nstderr: %s", err, stdout, stderr)
	}
	// Wait for their boot IDs to change.
	for _, name := range nodeNames {
		if err := wait.Poll(30*time.Second, 5*time.Minute, func() (bool, error) {
			node, err := f.ClientSet.Core().Nodes().Get(name)
			if err != nil {
				return false, fmt.Errorf("error getting node info after reboot: %s", err)
			}
			return node.Status.NodeInfo.BootID != oldBootIDs[name], nil
		}); err != nil {
			return fmt.Errorf("error waiting for node %s boot ID to change: %s", name, err)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package slackbot

import (
	"encoding/json"
	"fmt"
	"html"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
	"github.com/justinian/dice"
)

type Command struct {
	Name string
	Desc string
	Func func(*Instance, *Message, []string) error
}

var COMMANDS []*Command

func init() {
	COMMANDS = []*Command{
		&Command{"help", "Show a list of commands.", cmd_help},
		&Command{"status", "Show my current status.", cmd_status},
		&Command{"duck", "Quack.", cmd_duck},
		&Command{"vote", "start/stop a vote or vote yes/no during a vote.", cmd_vote},
		&Command{"mute", "Mute my messages to this channel, for a while.", cmd_mute},
		&Command{"roll", "Throw a dice roll.", cmd_roll},
		&Command{"wiki", "Quote a page from our SS13 wiki.", cmd_wiki},
		&Command{"pun", "Tell a random pun.", cmd_pun},
		&Command{"badpun", "Tell a random, bad pun.", cmd_pun},
		&Command{"catfact", "Tell a random cat fact.", cmd_catfact},
		&Command{"catfacts", "Tell a random cat fact.", cmd_catfact},
		&Command{"goon", "Tell a random quote from Goon's source code.", cmd_goon},
		&Command{"apollo", "Tell a random quote from Apollo's source code.", cmd_apollo},
	}
}

func cmd_help(i *Instance, m *Message, args []string) error {
	// TODO: sort the list
	tmp := "Available commands:\n"
	for _, c := range COMMANDS {
		tmp += fmt.Sprintf("- `%s\t%s`\n", c.Name, c.Desc)
	}
	i.UserMsg(m.User, tmp)
	return nil
}

func cmd_duck(i *Instance, m *Message, args []string) error {
	var quotes = []string{
		"Quack",
		"Wenk",
		"O RLY?",
		"Kraaawk!",
		"Bwaak",
		"Chirp",
	}
	i.ChannelMsg(m.Channel, quotes[rand.Intn(len(quotes))])
	return nil
}

func cmd_vote(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	if args[0] == "start" {
		i.StartVote(m.Channel)
		i.ChannelMsg(m.Channel, fmt.Sprintf("@%s has started a new vote! Tell me if you would like to `vote yes` or `vote no` on it.", i.Users[m.User].Name))
	} else if args[0] == "stop" {
		votes := i.StopVote(m.Channel)
		var result string
		if votes > 0 {
			result = "*YES* has won"
		} else if votes < 0 {
			result = "*NO* has won"
		} else {
			result = "It's a tie! No one won"
		}
		i.ChannelMsg(m.Channel, fmt.Sprintf("@%s has stopped the vote! The result is...\n%s (score: %d)!", i.Users[m.User].Name, result, votes))
	} else if args[0] == "yes" {
		i.Vote(+1, m.Channel)
	} else if args[0] == "no" {
		i.Vote(-1, m.Channel)
	}
	return nil
}

func cmd_mute(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	dur, e := time.ParseDuration(args[0])
	if e != nil {
		return fmt.Errorf("Couldn't parse a duration.")
	}
	if dur.Minutes() < 1 {
		dur = time.Duration(5) * time.Minute
	}
	if dur.Minutes() > 60 {
		dur = time.Duration(60) * time.Minute
	}

	i.ChannelMsg(m.Channel, fmt.Sprintf("I will now shut up for ~%.0f minutes.", dur.Minutes()))
	go func() {
		time.Sleep(5)
		i.Mute(m.Channel, dur)
	}()
	return nil
}

func cmd_status(i *Instance, m *Message, args []string) error {
	tmp := "My current status:\n"
	tmp += fmt.Sprintf("`Running: %v`\n", i.running)
	tmp += fmt.Sprintf("`Version: v%v`\n", VERSION)
	tmp += fmt.Sprintf("`Debug mode: %v`\n", i.Debug)
	tmp += fmt.Sprintf("`Latency: %v`\n", i.Latency)
	tmp += fmt.Sprintf("`My User ID: @%v`\n", i.BotId)
	tmp += fmt.Sprintf("`Tracked channels: %v`\n", len(i.Channels))
	tmp += fmt.Sprintf("`Tracked users: %v`\n", len(i.Users))
	tmp += fmt.Sprintf("`No. of Goon quotes: %v`\n", len(i.goon))
	tmp += fmt.Sprintf("`No. of Apollo quotes: %v`\n", len(i.apollo))
	tmp += fmt.Sprintf("\nI am currently muted on channels:\n")
	if len(i.mutes) < 1 {
		tmp += "- `None`\n"
	} else {
		for k, v := range i.mutes {
			c := i.Channels[k].Name
			t := v.Sub(time.Now())
			tmp += fmt.Sprintf("- `%v (ends in ~%.0f minutes)`\n", c, t.Minutes())
		}
	}
	i.UserMsg(m.User, tmp)
	return nil
}

func cmd_roll(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	ret, res, e := dice.Roll(args[0])
	if e != nil {
		return fmt.Errorf("Bad dice format.")
	}
	i.ChannelMsg(m.Channel, fmt.Sprintf("@%s has rolled: %v, %v\n", i.Users[m.User].Name, ret, res))
	return nil
}

func cmd_wiki(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	u := WIKI_URL + url.QueryEscape(args[0])
	doc, e := goquery.NewDocument(u)
	if e != nil {
		return fmt.Errorf("Couldn't open the wiki for you (%v).", u)
	}

	node := doc.Find("div #mw-content-text > p").First()
	text := strings.TrimSpace(node.Text())
	if node.Length() < 1 || len(text) < 1 {
		return fmt.Errorf("Couldn't quote that page for you (%v).", u)
	}

	i.ChannelMsg(m.Channel, fmt.Sprintf(">>>%s\n`Source: %s`", text, u))
	return nil
}

func cmd_pun(i *Instance, m *Message, args []string) error {
	resp, e := http.Get("http://www.punoftheday.com/cgi-bin/arandompun.pl")
	if e != nil {
		return fmt.Errorf("Sorry, couldn't make up a pun for you.")
	}
	defer resp.Body.Close()
	body, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		return fmt.Errorf("Sorry, couldn't make up a pun for you.")
	}
	// Yep this is a fucking mess.
	s := strings.TrimSpace(string(body))
	s = strings.TrimPrefix(s, "document.write('"")
	index := strings.Index(s, """)
	s = html.UnescapeString(s[:index])
	i.ChannelMsg(m.Channel, fmt.Sprintf(">>>%v\n`© 1996-2011 PunoftheDay.com`", s))
	return nil
}

type CatFacts struct {
	Facts   []string
	Success string
}

var LAST_CATFACT_TIME time.Time

func cmd_catfact(i *Instance, m *Message, args []string) error {
	now := time.Now()
	if now.After(LAST_CATFACT_TIME) != true {
		return fmt.Errorf("Sorry, I can only show a single catfact per day (or else I'll get banned!).")
	}
	LAST_CATFACT_TIME = now.Add(24 * time.Hour)

	resp, e := http.Get("http://catfacts-api.appspot.com/api/facts?number=1")
	if e != nil {
		return fmt.Errorf("Sorry, couldn't find any cat facts.")
	}

	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	var cf CatFacts
	e = decoder.Decode(&cf)
	if e != nil {
		return fmt.Errorf("Sorry, couldn't find any cat facts.")
	}

	if len(cf.Facts) > 0 {
		msg := fmt.Sprintf(">>>%v\n`© http://catfacts-api.appspot.com`", cf.Facts[0])
		i.ChannelMsg(m.Channel, msg)
		return nil
	}
	return fmt.Errorf("Sorry, couldn't find any cat facts.")
}

func cmd_goon(i *Instance, m *Message, args []string) error {
	q := i.random_goon_quote()
	msg := fmt.Sprintf(">>>%v\n`%v`", q.Quote, q.File)
	i.ChannelMsg(m.Channel, msg)
	return nil
}
func cmd_apollo(i *Instance, m *Message, args []string) error {
	q := i.random_apollo_quote()
	msg := fmt.Sprintf(">>>%v\n`%v`", q.Quote, q.File)
	i.ChannelMsg(m.Channel, msg)
	return nil
}
<commit_msg>Remove multiple names for same commands.<commit_after>package slackbot

import (
	"encoding/json"
	"fmt"
	"html"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
	"github.com/justinian/dice"
)

type Command struct {
	Name string
	Desc string
	Func func(*Instance, *Message, []string) error
}

var COMMANDS []*Command

func init() {
	COMMANDS = []*Command{
		&Command{"help", "Show a list of commands.", cmd_help},
		&Command{"status", "Show my current status.", cmd_status},
		&Command{"duck", "Quack.", cmd_duck},
		&Command{"vote", "start/stop a vote or vote yes/no during a vote.", cmd_vote},
		&Command{"mute", "Mute my messages to this channel, for a while.", cmd_mute},
		&Command{"roll", "Throw a dice roll.", cmd_roll},
		&Command{"wiki", "Quote a page from our SS13 wiki.", cmd_wiki},
		&Command{"pun", "Tell a random pun.", cmd_pun},
		&Command{"catfact", "Tell a random cat fact.", cmd_catfact},
		&Command{"goon", "Tell a random quote from Goon's source code.", cmd_goon},
		&Command{"apollo", "Tell a random quote from Apollo's source code.", cmd_apollo},
	}
}

func cmd_help(i *Instance, m *Message, args []string) error {
	// TODO: sort the list
	tmp := "Available commands:\n"
	for _, c := range COMMANDS {
		tmp += fmt.Sprintf("- `%s\t%s`\n", c.Name, c.Desc)
	}
	i.UserMsg(m.User, tmp)
	return nil
}

func cmd_duck(i *Instance, m *Message, args []string) error {
	var quotes = []string{
		"Quack",
		"Wenk",
		"O RLY?",
		"Kraaawk!",
		"Bwaak",
		"Chirp",
	}
	i.ChannelMsg(m.Channel, quotes[rand.Intn(len(quotes))])
	return nil
}

func cmd_vote(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	if args[0] == "start" {
		i.StartVote(m.Channel)
		i.ChannelMsg(m.Channel, fmt.Sprintf("@%s has started a new vote! Tell me if you would like to `vote yes` or `vote no` on it.", i.Users[m.User].Name))
	} else if args[0] == "stop" {
		votes := i.StopVote(m.Channel)
		var result string
		if votes > 0 {
			result = "*YES* has won"
		} else if votes < 0 {
			result = "*NO* has won"
		} else {
			result = "It's a tie! No one won"
		}
		i.ChannelMsg(m.Channel, fmt.Sprintf("@%s has stopped the vote! The result is...\n%s (score: %d)!", i.Users[m.User].Name, result, votes))
	} else if args[0] == "yes" {
		i.Vote(+1, m.Channel)
	} else if args[0] == "no" {
		i.Vote(-1, m.Channel)
	}
	return nil
}

func cmd_mute(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	dur, e := time.ParseDuration(args[0])
	if e != nil {
		return fmt.Errorf("Couldn't parse a duration.")
	}
	if dur.Minutes() < 1 {
		dur = time.Duration(5) * time.Minute
	}
	if dur.Minutes() > 60 {
		dur = time.Duration(60) * time.Minute
	}

	i.ChannelMsg(m.Channel, fmt.Sprintf("I will now shut up for ~%.0f minutes.", dur.Minutes()))
	go func() {
		time.Sleep(5)
		i.Mute(m.Channel, dur)
	}()
	return nil
}

func cmd_status(i *Instance, m *Message, args []string) error {
	tmp := "My current status:\n"
	tmp += fmt.Sprintf("`Running: %v`\n", i.running)
	tmp += fmt.Sprintf("`Version: v%v`\n", VERSION)
	tmp += fmt.Sprintf("`Debug mode: %v`\n", i.Debug)
	tmp += fmt.Sprintf("`Latency: %v`\n", i.Latency)
	tmp += fmt.Sprintf("`My User ID: @%v`\n", i.BotId)
	tmp += fmt.Sprintf("`Tracked channels: %v`\n", len(i.Channels))
	tmp += fmt.Sprintf("`Tracked users: %v`\n", len(i.Users))
	tmp += fmt.Sprintf("`No. of Goon quotes: %v`\n", len(i.goon))
	tmp += fmt.Sprintf("`No. of Apollo quotes: %v`\n", len(i.apollo))
	tmp += fmt.Sprintf("\nI am currently muted on channels:\n")
	if len(i.mutes) < 1 {
		tmp += "- `None`\n"
	} else {
		for k, v := range i.mutes {
			c := i.Channels[k].Name
			t := v.Sub(time.Now())
			tmp += fmt.Sprintf("- `%v (ends in ~%.0f minutes)`\n", c, t.Minutes())
		}
	}
	i.UserMsg(m.User, tmp)
	return nil
}

func cmd_roll(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	ret, res, e := dice.Roll(args[0])
	if e != nil {
		return fmt.Errorf("Bad dice format.")
	}
	i.ChannelMsg(m.Channel, fmt.Sprintf("@%s has rolled: %v, %v\n", i.Users[m.User].Name, ret, res))
	return nil
}

func cmd_wiki(i *Instance, m *Message, args []string) error {
	if len(args) < 1 {
		return fmt.Errorf("Missing argument.")
	}

	u := WIKI_URL + url.QueryEscape(args[0])
	doc, e := goquery.NewDocument(u)
	if e != nil {
		return fmt.Errorf("Couldn't open the wiki for you (%v).", u)
	}

	node := doc.Find("div #mw-content-text > p").First()
	text := strings.TrimSpace(node.Text())
	if node.Length() < 1 || len(text) < 1 {
		return fmt.Errorf("Couldn't quote that page for you (%v).", u)
	}

	i.ChannelMsg(m.Channel, fmt.Sprintf(">>>%s\n`Source: %s`", text, u))
	return nil
}

func cmd_pun(i *Instance, m *Message, args []string) error {
	resp, e := http.Get("http://www.punoftheday.com/cgi-bin/arandompun.pl")
	if e != nil {
		return fmt.Errorf("Sorry, couldn't make up a pun for you.")
	}
	defer resp.Body.Close()
	body, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		return fmt.Errorf("Sorry, couldn't make up a pun for you.")
	}
	// Yep this is a fucking mess.
	s := strings.TrimSpace(string(body))
	s = strings.TrimPrefix(s, "document.write('"")
	index := strings.Index(s, """)
	s = html.UnescapeString(s[:index])
	i.ChannelMsg(m.Channel, fmt.Sprintf(">>>%v\n`© 1996-2011 PunoftheDay.com`", s))
	return nil
}

type CatFacts struct {
	Facts   []string
	Success string
}

var LAST_CATFACT_TIME time.Time

func cmd_catfact(i *Instance, m *Message, args []string) error {
	now := time.Now()
	if now.After(LAST_CATFACT_TIME) != true {
		return fmt.Errorf("Sorry, I can only show a single catfact per day (or else I'll get banned!).")
	}
	LAST_CATFACT_TIME = now.Add(24 * time.Hour)

	resp, e := http.Get("http://catfacts-api.appspot.com/api/facts?number=1")
	if e != nil {
		return fmt.Errorf("Sorry, couldn't find any cat facts.")
	}

	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	var cf CatFacts
	e = decoder.Decode(&cf)
	if e != nil {
		return fmt.Errorf("Sorry, couldn't find any cat facts.")
	}

	if len(cf.Facts) > 0 {
		msg := fmt.Sprintf(">>>%v\n`© http://catfacts-api.appspot.com`", cf.Facts[0])
		i.ChannelMsg(m.Channel, msg)
		return nil
	}
	return fmt.Errorf("Sorry, couldn't find any cat facts.")
}

func cmd_goon(i *Instance, m *Message, args []string) error {
	q := i.random_goon_quote()
	msg := fmt.Sprintf(">>>%v\n`%v`", q.Quote, q.File)
	i.ChannelMsg(m.Channel, msg)
	return nil
}
func cmd_apollo(i *Instance, m *Message, args []string) error {
	q := i.random_apollo_quote()
	msg := fmt.Sprintf(">>>%v\n`%v`", q.Quote, q.File)
	i.ChannelMsg(m.Channel, msg)
	return nil
}
<|endoftext|>


<commit_before>package parse

import "fmt"

type Parser struct {
	l *lexer
}

func NewParser(name, input string) *Parser {
	p := &Parser{l: lex(name, input)}
	return p
}

func (p *Parser) Parse() (string, error) {
	str := "
\n"
	for {
		tok := p.l.nextToken()
		//fmt.Printf("%s\n", tok)
		switch tok.typ {
		case tokenEOF:
			str += "
\n"
			return str, nil
		case tokenError:
			return "", fmt.Errorf("%s:%d: %s",
				p.l.name,
				tok.line,
				tok.val,
			)
		case tokenParagraphDelim:
			str += fmt.Sprintf("\n
\n
\n")
		case tokenNewline:
			str += fmt.Sprintf("
\n")
		case tokenText:
			str += tok.val
		case tokenComment:
			str += fmt.Sprintf("\n", tok.val)
		}
	}

	str += "
"

	return str, nil
}<commit_msg>Escape html in text, but preserve prefixed whitespace.<commit_after>package parse

import (
	"fmt"
	"html"
)

type Parser struct {
	l *lexer
}

func NewParser(name, input string) *Parser {
	p := &Parser{l: lex(name, input)}
	return p
}

func (p *Parser) Parse() (string, error) {
	str := "
\n"
	for {
		tok := p.l.nextToken()
		//fmt.Printf("%s\n", tok)
		switch tok.typ {
		case tokenEOF:
			str += "
\n"
			return str, nil
		case tokenError:
			return "", fmt.Errorf("%s:%d: %s",
				p.l.name,
				tok.line,
				tok.val,
			)
		case tokenParagraphDelim:
			str += fmt.Sprintf("\n
\n
\n")
		case tokenNewline:
			str += fmt.Sprintf("
\n")
		case tokenText:
			str += toHtml(tok.val)
		case tokenComment:
			str += fmt.Sprintf("\n", tok.val)
		}
	}

	str += "
"

	return str, nil
}

func toHtml(s string) string {
	var result string
	s = html.EscapeString(s)
Loop:
	for i := 0; i < len(s); i++ {
		switch s[i] {
		case ' ':
			result += " "
		case '\t':
			result += "    "
		default:
			result += s[i:]
			break Loop
		}
	}
	return result
}
<|endoftext|>


<commit_before>package goczmq

import (
	"testing"
)

func TestPoller(t *testing.T) {
	pullSock1, err := NewPULL("inproc://poller_pull1")
	if err != nil {
		t.Errorf("NewPULL failed: %s", err)
	}

	poller, err := NewPoller(pullSock1)
	if err != nil {
		t.Errorf("NewPoller failed: %s", err)
	}

	if len(poller.zsocks) != 1 {
		t.Errorf("Expected number of zsocks to be 1, was %d", len(poller.zsocks))
	}

	pullSock2, err := NewPULL("inproc://poller_pull2")
	if err != nil {
		t.Errorf("NewPULL failed: %s", err)
	}

	err = poller.Add(pullSock2)
	if err != nil {
		t.Errorf("poller Add failed: %s", err)
	}

	if len(poller.zsocks) != 2 {
		t.Errorf("Expected number of zsocks to be 2, was %d", len(poller.zsocks))
	}

	pushSock, err := NewPUSH("inproc://poller_pull1")
	if err != nil {
		t.Errorf("NewPUSH failed: %s", err)
	}

	err = pushSock.SendString("Hello", 0)
	if err != nil {
		t.Errorf("SendMessage failed: %s", err)
	}

	s := poller.Wait(0)
	if s == nil {
		t.Errorf("Wait did not return waiting socket")
	}

	msg, err := s.RecvString()
	if err != nil {
		t.Errorf("RecvMessage failed: %s", err)
	}

	if msg != "Hello" {
		t.Errorf("Expected 'Hello', received %s", msg)
	}

	pushSock2, err := NewPUSH("inproc://poller_pull2")
	if err != nil {
		t.Errorf("NewPUSH failed: %s", err)
	}

	err = pushSock2.SendString("World", 0)
	if err != nil {
		t.Errorf("SendMessage failed: %s", err)
	}

	s = poller.Wait(0)
	if s == nil {
		t.Errorf("Wait did not return waiting socket")
	}

	msg, err = s.RecvString()
	if err != nil {
		t.Errorf("RecvMessage failed: %s", err)
	}

	if msg != "World" {
		t.Errorf("Expected 'World', received %s", msg)
	}

	poller.Remove(pullSock2)
	if len(poller.zsocks) != 1 {
		t.Errorf("zsocks len should be 1 after removing pushsock, is %d", len(poller.zsocks))
	}
	poller.Destroy()
}
<commit_msg>adding destroy for second pull socket in poller test<commit_after>package goczmq

import (
	"testing"
)

func TestPoller(t *testing.T) {
	pullSock1, err := NewPULL("inproc://poller_pull1")
	if err != nil {
		t.Errorf("NewPULL failed: %s", err)
	}

	poller, err := NewPoller(pullSock1)
	if err != nil {
		t.Errorf("NewPoller failed: %s", err)
	}

	if len(poller.zsocks) != 1 {
		t.Errorf("Expected number of zsocks to be 1, was %d", len(poller.zsocks))
	}

	pullSock2, err := NewPULL("inproc://poller_pull2")
	if err != nil {
		t.Errorf("NewPULL failed: %s", err)
	}

	err = poller.Add(pullSock2)
	if err != nil {
		t.Errorf("poller Add failed: %s", err)
	}

	if len(poller.zsocks) != 2 {
		t.Errorf("Expected number of zsocks to be 2, was %d", len(poller.zsocks))
	}

	pushSock, err := NewPUSH("inproc://poller_pull1")
	if err != nil {
		t.Errorf("NewPUSH failed: %s", err)
	}

	err = pushSock.SendString("Hello", 0)
	if err != nil {
		t.Errorf("SendMessage failed: %s", err)
	}

	s := poller.Wait(0)
	if s == nil {
		t.Errorf("Wait did not return waiting socket")
	}

	msg, err := s.RecvString()
	if err != nil {
		t.Errorf("RecvMessage failed: %s", err)
	}

	if msg != "Hello" {
		t.Errorf("Expected 'Hello', received %s", msg)
	}

	pushSock2, err := NewPUSH("inproc://poller_pull2")
	if err != nil {
		t.Errorf("NewPUSH failed: %s", err)
	}

	err = pushSock2.SendString("World", 0)
	if err != nil {
		t.Errorf("SendMessage failed: %s", err)
	}

	s = poller.Wait(0)
	if s == nil {
		t.Errorf("Wait did not return waiting socket")
	}

	msg, err = s.RecvString()
	if err != nil {
		t.Errorf("RecvMessage failed: %s", err)
	}

	if msg != "World" {
		t.Errorf("Expected 'World', received %s", msg)
	}

	poller.Remove(pullSock2)
	if len(poller.zsocks) != 1 {
		t.Errorf("zsocks len should be 1 after removing pushsock, is %d", len(poller.zsocks))
	}

	pullSock2.Destroy()
	poller.Destroy()
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package charmstore

import (
	"gopkg.in/errgo.v1"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/juju/charmstore/internal/mongodoc"
	"github.com/juju/charmstore/params"
)

// migrations holds all the migration functions that are executed in the order
// they are defined when the charm store server is started. Each migration is
// associated with a name that is used to check whether the migration has been
// already run. To introduce a new database migration, add the corresponding
// migration name and function to this list, and update the
// TestMigrateMigrationList test in migration_test.go adding the new name(s).
// Note that migration names must be unique across the list.
var migrations = []migration{{
	name:    "entity ids denormalization",
	migrate: denormalizeEntityIds,
}, {
	name:    "base entities creation",
	migrate: createBaseEntities,
}, {
	name:    "read acl creation",
	migrate: populateReadACL,
}}

// migration holds a migration function with its corresponding name.
type migration struct {
	name    string
	migrate func(StoreDatabase) error
}

// Migrate starts the migration process using the given database.
func migrate(db StoreDatabase) error {
	// Retrieve already executed migrations.
	executed, err := getExecuted(db)
	if err != nil {
		return errgo.Mask(err)
	}

	// Execute required migrations.
	for _, m := range migrations {
		if executed[m.name] {
			logger.Debugf("skipping already executed migration: %s", m.name)
			continue
		}
		logger.Infof("starting migration: %s", m.name)
		if err := m.migrate(db); err != nil {
			return errgo.Notef(err, "error executing migration: %s", m.name)
		}
		if err := setExecuted(db, m.name); err != nil {
			return errgo.Mask(err)
		}
		logger.Infof("migration completed: %s", m.name)
	}
	return nil
}

func getExecuted(db StoreDatabase) (map[string]bool, error) {
	// Retrieve the already executed migration names.
	executed := make(map[string]bool)
	var doc mongodoc.Migration
	if err := db.Migrations().Find(nil).Select(bson.D{{"executed", 1}}).One(&doc); err != nil {
		if err == mgo.ErrNotFound {
			return executed, nil
		}
		return nil, errgo.Notef(err, "cannot retrieve executed migrations")
	}

	names := make(map[string]bool, len(migrations))
	for _, m := range migrations {
		names[m.name] = true
	}
	for _, name := range doc.Executed {
		// Check that the already executed migrations are known.
		if !names[name] {
			return nil, errgo.Newf("found unknown migration %q; running old charm store code on newer charm store database?", name)
		}
		// Collect the name of the executed migration.
		executed[name] = true
	}
	return executed, nil
}

func setExecuted(db StoreDatabase, name string) error {
	if _, err := db.Migrations().Upsert(nil, bson.D{{
		"$addToSet", bson.D{{"executed", name}},
	}}); err != nil {
		return errgo.Notef(err, "cannot add %s to executed migrations", name)
	}
	return nil
}

// denormalizeEntityIds adds the user, name, revision and series fields to
// entities where those fields are missing.
// This function is not supposed to be called directly.
func denormalizeEntityIds(db StoreDatabase) error {
	entities := db.Entities()
	var entity mongodoc.Entity
	iter := entities.Find(bson.D{{
		// Use the name field to collect not migrated entities.
		"name", bson.D{{"$exists", false}},
	}}).Select(bson.D{{"_id", 1}}).Iter()
	defer iter.Close()

	for iter.Next(&entity) {
		logger.Infof("updating %s", entity.URL)
		if err := entities.UpdateId(entity.URL, bson.D{{
			"$set", bson.D{
				{"user", entity.URL.User},
				{"name", entity.URL.Name},
				{"revision", entity.URL.Revision},
				{"series", entity.URL.Series},
			},
		}}); err != nil {
			return errgo.Notef(err, "cannot denormalize entity id %s", entity.URL)
		}
	}
	if err := iter.Close(); err != nil {
		return errgo.Notef(err, "cannot denormalize entity ids")
	}
	return nil
}

// createBaseEntities creates base entities for each entity in the database.
func createBaseEntities(db StoreDatabase) error {
	baseEntities := db.BaseEntities()
	counter := 0

	var entity mongodoc.Entity
	iter := db.Entities().Find(nil).Select(bson.D{{"baseurl", 1}}).Iter()
	defer iter.Close()

	for iter.Next(&entity) {
		baseEntity := &mongodoc.BaseEntity{
			URL:    entity.BaseURL,
			Name:   entity.BaseURL.Name,
			User:   entity.BaseURL.User,
			Public: true,
		}
		err := baseEntities.Insert(baseEntity)
		if err == nil {
			counter++
		} else if !mgo.IsDup(err) {
			return errgo.Notef(err, "cannot create base entity %s", entity.BaseURL)
		}

	}
	if err := iter.Close(); err != nil {
		return errgo.Notef(err, "cannot create base entities")
	}
	logger.Infof("%d base entities created", counter)
	return nil
}

// populateReadACL adds the read ACL to base entities not having it.
func populateReadACL(db StoreDatabase) error {
	baseEntities := db.BaseEntities()
	var entity mongodoc.BaseEntity
	iter := baseEntities.Find(bson.D{{
		"acls.read", bson.D{{"$size", 0}},
	}}).Select(bson.D{{"_id", 1}}).Iter()
	defer iter.Close()

	counter := 0
	for iter.Next(&entity) {
		readPerm := everyonePerm
		if entity.URL.User != "" {
			readPerm = []string{params.Everyone, entity.URL.User}
		}
		if err := baseEntities.UpdateId(entity.URL, bson.D{{
			"$set", bson.D{{"acls.read", readPerm}},
		}}); err != nil {
			return errgo.Notef(err, "cannot populate ACL for base entity %s", entity.URL)
		}
		counter++
	}
	if err := iter.Close(); err != nil {
		return errgo.Notef(err, "cannot populate ACLs for base entities")
	}
	logger.Infof("%d base entities updated", counter)
	return nil
}
<commit_msg>migrations: improve error messages when closing the iterators fails.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package charmstore

import (
	"gopkg.in/errgo.v1"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/juju/charmstore/internal/mongodoc"
	"github.com/juju/charmstore/params"
)

// migrations holds all the migration functions that are executed in the order
// they are defined when the charm store server is started. Each migration is
// associated with a name that is used to check whether the migration has been
// already run. To introduce a new database migration, add the corresponding
// migration name and function to this list, and update the
// TestMigrateMigrationList test in migration_test.go adding the new name(s).
// Note that migration names must be unique across the list.
var migrations = []migration{{
	name:    "entity ids denormalization",
	migrate: denormalizeEntityIds,
}, {
	name:    "base entities creation",
	migrate: createBaseEntities,
}, {
	name:    "read acl creation",
	migrate: populateReadACL,
}}

// migration holds a migration function with its corresponding name.
type migration struct {
	name    string
	migrate func(StoreDatabase) error
}

// Migrate starts the migration process using the given database.
func migrate(db StoreDatabase) error {
	// Retrieve already executed migrations.
	executed, err := getExecuted(db)
	if err != nil {
		return errgo.Mask(err)
	}

	// Execute required migrations.
	for _, m := range migrations {
		if executed[m.name] {
			logger.Debugf("skipping already executed migration: %s", m.name)
			continue
		}
		logger.Infof("starting migration: %s", m.name)
		if err := m.migrate(db); err != nil {
			return errgo.Notef(err, "error executing migration: %s", m.name)
		}
		if err := setExecuted(db, m.name); err != nil {
			return errgo.Mask(err)
		}
		logger.Infof("migration completed: %s", m.name)
	}
	return nil
}

func getExecuted(db StoreDatabase) (map[string]bool, error) {
	// Retrieve the already executed migration names.
	executed := make(map[string]bool)
	var doc mongodoc.Migration
	if err := db.Migrations().Find(nil).Select(bson.D{{"executed", 1}}).One(&doc); err != nil {
		if err == mgo.ErrNotFound {
			return executed, nil
		}
		return nil, errgo.Notef(err, "cannot retrieve executed migrations")
	}

	names := make(map[string]bool, len(migrations))
	for _, m := range migrations {
		names[m.name] = true
	}
	for _, name := range doc.Executed {
		// Check that the already executed migrations are known.
		if !names[name] {
			return nil, errgo.Newf("found unknown migration %q; running old charm store code on newer charm store database?", name)
		}
		// Collect the name of the executed migration.
		executed[name] = true
	}
	return executed, nil
}

func setExecuted(db StoreDatabase, name string) error {
	if _, err := db.Migrations().Upsert(nil, bson.D{{
		"$addToSet", bson.D{{"executed", name}},
	}}); err != nil {
		return errgo.Notef(err, "cannot add %s to executed migrations", name)
	}
	return nil
}

// denormalizeEntityIds adds the user, name, revision and series fields to
// entities where those fields are missing.
// This function is not supposed to be called directly.
func denormalizeEntityIds(db StoreDatabase) error {
	entities := db.Entities()
	var entity mongodoc.Entity
	iter := entities.Find(bson.D{{
		// Use the name field to collect not migrated entities.
		"name", bson.D{{"$exists", false}},
	}}).Select(bson.D{{"_id", 1}}).Iter()
	defer iter.Close()

	for iter.Next(&entity) {
		logger.Infof("updating %s", entity.URL)
		if err := entities.UpdateId(entity.URL, bson.D{{
			"$set", bson.D{
				{"user", entity.URL.User},
				{"name", entity.URL.Name},
				{"revision", entity.URL.Revision},
				{"series", entity.URL.Series},
			},
		}}); err != nil {
			return errgo.Notef(err, "cannot denormalize entity id %s", entity.URL)
		}
	}
	if err := iter.Close(); err != nil {
		return errgo.Notef(err, "cannot iterate entities")
	}
	return nil
}

// createBaseEntities creates base entities for each entity in the database.
func createBaseEntities(db StoreDatabase) error {
	baseEntities := db.BaseEntities()
	counter := 0

	var entity mongodoc.Entity
	iter := db.Entities().Find(nil).Select(bson.D{{"baseurl", 1}}).Iter()
	defer iter.Close()

	for iter.Next(&entity) {
		baseEntity := &mongodoc.BaseEntity{
			URL:    entity.BaseURL,
			Name:   entity.BaseURL.Name,
			User:   entity.BaseURL.User,
			Public: true,
		}
		err := baseEntities.Insert(baseEntity)
		if err == nil {
			counter++
		} else if !mgo.IsDup(err) {
			return errgo.Notef(err, "cannot create base entity %s", entity.BaseURL)
		}

	}
	if err := iter.Close(); err != nil {
		return errgo.Notef(err, "cannot iterate base entities")
	}
	logger.Infof("%d base entities created", counter)
	return nil
}

// populateReadACL adds the read ACL to base entities not having it.
func populateReadACL(db StoreDatabase) error {
	baseEntities := db.BaseEntities()
	var entity mongodoc.BaseEntity
	iter := baseEntities.Find(bson.D{{
		"acls.read", bson.D{{"$size", 0}},
	}}).Select(bson.D{{"_id", 1}}).Iter()
	defer iter.Close()

	counter := 0
	for iter.Next(&entity) {
		readPerm := everyonePerm
		if entity.URL.User != "" {
			readPerm = []string{params.Everyone, entity.URL.User}
		}
		if err := baseEntities.UpdateId(entity.URL, bson.D{{
			"$set", bson.D{{"acls.read", readPerm}},
		}}); err != nil {
			return errgo.Notef(err, "cannot populate ACL for base entity %s", entity.URL)
		}
		counter++
	}
	if err := iter.Close(); err != nil {
		return errgo.Notef(err, "cannot iterate base entities")
	}
	logger.Infof("%d base entities updated", counter)
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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 checktools provides functionns to check all tools are correctly installed.
package checktools

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"

	"github.com/Masterminds/semver"
)

var (
	// minPackVersion is the minimum required version of pack.
	minPackVersion = semver.MustParse("0.23.0")
)

// Installed checks that all required tools are on PATH.
func Installed() error {
	tools := []struct {
		name string
		url  string
	}{
		{"pack", "https://buildpacks.io/docs/install-pack/"},
		{"docker", "https://docs.docker.com/install/"},
		{"container-structure-test", "https://github.com/GoogleContainerTools/container-structure-test#installation"},
	}

	for _, tool := range tools {
		path, err := exec.LookPath(tool.name)
		if err != nil {
			return fmt.Errorf("%s not found, please follow %s and ensure it is on $PATH: %s", tool.name, tool.url, os.Getenv("PATH"))
		}
		log.Printf("%s found at %s", tool.name, path)
	}
	return nil
}

// PackVersion checks that the installed pack has the correct version.
func PackVersion() error {
	// pack requires $HOME to exist.
	home, err := ioutil.TempDir("", "pack-home")
	if err != nil {
		return err
	}
	defer os.RemoveAll(home)

	path, err := exec.LookPath("pack")
	if err != nil {
		return fmt.Errorf("finding pack on PATH: %w", err)
	}
	cmd := exec.Command(path, "--version")
	cmd.Env = append(os.Environ(), "HOME="+home)
	out, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("running pack: %v", err)
	}
	log.Printf("Found pack version %s", out)
	// Remove the build suffix so it can be parsed by semver andt the error message is less confusing.
	// For example, instead of `0.13.1+git-4134cc6.build-1135` use `0.13.1`.
	version, err := semver.NewVersion(strings.Split(string(out), "+")[0])
	if err != nil {
		return fmt.Errorf("parsing semver from %s: %v", out, err)
	}

	if version.LessThan(minPackVersion) {
		return fmt.Errorf("outdated pack binary (%s): want %s, got %s; to update please follow https://buildpacks.io/docs/install-pack/", path, minPackVersion, version)
	}
	return nil
}
<commit_msg>Add IFTTT check for min pack version docs.<commit_after>// Copyright 2020 Google LLC
//
// 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 checktools provides functionns to check all tools are correctly installed.
package checktools

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"

	"github.com/Masterminds/semver"
)

var (
	// LINT.IfChange(minPackVersion)
	// minPackVersion is the minimum required version of pack.
	minPackVersion = semver.MustParse("0.23.0")
	// LINT.ThenChange(//depot/google3/apphosting/g3doc/runtimes/tutorials/buildpack-tests-debug.md)
)

// Installed checks that all required tools are on PATH.
func Installed() error {
	tools := []struct {
		name string
		url  string
	}{
		{"pack", "https://buildpacks.io/docs/install-pack/"},
		{"docker", "https://docs.docker.com/install/"},
		{"container-structure-test", "https://github.com/GoogleContainerTools/container-structure-test#installation"},
	}

	for _, tool := range tools {
		path, err := exec.LookPath(tool.name)
		if err != nil {
			return fmt.Errorf("%s not found, please follow %s and ensure it is on $PATH: %s", tool.name, tool.url, os.Getenv("PATH"))
		}
		log.Printf("%s found at %s", tool.name, path)
	}
	return nil
}

// PackVersion checks that the installed pack has the correct version.
func PackVersion() error {
	// pack requires $HOME to exist.
	home, err := ioutil.TempDir("", "pack-home")
	if err != nil {
		return err
	}
	defer os.RemoveAll(home)

	path, err := exec.LookPath("pack")
	if err != nil {
		return fmt.Errorf("finding pack on PATH: %w", err)
	}
	cmd := exec.Command(path, "--version")
	cmd.Env = append(os.Environ(), "HOME="+home)
	out, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("running pack: %v", err)
	}
	log.Printf("Found pack version %s", out)
	// Remove the build suffix so it can be parsed by semver andt the error message is less confusing.
	// For example, instead of `0.13.1+git-4134cc6.build-1135` use `0.13.1`.
	version, err := semver.NewVersion(strings.Split(string(out), "+")[0])
	if err != nil {
		return fmt.Errorf("parsing semver from %s: %v", out, err)
	}

	if version.LessThan(minPackVersion) {
		return fmt.Errorf("outdated pack binary (%s): want %s, got %s; to update please follow https://buildpacks.io/docs/install-pack/", path, minPackVersion, version)
	}
	return nil
}
<|endoftext|>