<commit_before>package api

import (
	"net/http"

	"github.com/labstack/echo"
)

type Prefix struct {
	Background string   `json:"background"`
	Color      string   `json:"color"`
	Words      []string `json:"words"`
	TimedEvent bool     `json:"timedEvent"`
	Default    bool     `json:"default"`
}

var DefaultPrefixes = []Prefix{
	Prefix{
		Background: "4C6C9B",
		Color:      "FFFFFF",
		Words:      []string{"HW", "Read", "Reading"},
		Default:    true,
	},
	Prefix{
		Background: "9ACD32",
		Color:      "FFFFFF",
		Words:      []string{"Project"},
		Default:    true,
	},
	Prefix{
		Background: "C3A528",
		Color:      "FFFFFF",
		Words:      []string{"Report", "Essay", "Paper", "Write"},
		Default:    true,
	},
	Prefix{
		Background: "FFA500",
		Color:      "FFFFFF",
		Words:      []string{"Quiz", "PopQuiz", "GradedHW", "GradedHomework"},
		Default:    true,
	},
	Prefix{
		Background: "DC143C",
		Color:      "FFFFFF",
		Words:      []string{"Test", "Final", "Exam", "Midterm", "Ahh"},
		Default:    true,
	},
	Prefix{
		Background: "2AC0F1",
		Color:      "FFFFFF",
		Words:      []string{"ICA", "FieldTrip", "Thingy"},
		Default:    true,
	},
	Prefix{
		Background: "2AF15E",
		Color:      "FFFFFF",
		Words:      []string{"Lab", "Study", "Memorize"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "003DAD",
		Color:      "FFFFFF",
		Words:      []string{"DocID"},
		Default:    true,
	},
	Prefix{
		Background: "000000",
		Color:      "00FF00",
		Words:      []string{"Trojun", "Hex"},
		Default:    true,
	},
	Prefix{
		Background: "5000BC",
		Color:      "FFFFFF",
		Words:      []string{"OptionalHW", "Challenge"},
		Default:    true,
	},
	Prefix{
		Background: "000099",
		Color:      "FFFFFF",
		Words:      []string{"Presentation", "Prez"},
		Default:    true,
	},
	Prefix{
		Background: "123456",
		Color:      "FFFFFF",
		Words:      []string{"BuildSession", "Build"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "5A1B87",
		Color:      "FFFFFF",
		Words:      []string{"Meeting", "Meet"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "01b501",
		Color:      "FFFFFF",
		Words:      []string{"Begin", "Start", "Do"},
		TimedEvent: true,
		Default:    true,
	},
}

type PrefixesResponse struct {
	Status             string   `json:"status"`
	Prefixes           []Prefix `json:"prefixes"`
	FallbackBackground string   `json:"fallbackBackground"`
	FallbackColor      string   `json:"fallbackColor"`
}

func InitPrefixesAPI(e *echo.Echo) {
	e.GET("/prefixes/getDefaultList", func(c echo.Context) error {
		return c.JSON(http.StatusOK, PrefixesResponse{"ok", DefaultPrefixes, "FFD3BD", "000000"})
	})

	e.GET("/prefixes/getList", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}

		return c.JSON(http.StatusOK, PrefixesResponse{"ok", DefaultPrefixes, "FFD3BD", "000000"})
	})
}
<commit_msg>add new fun college application process tags and make begin tag consistent with others<commit_after>package api

import (
	"net/http"

	"github.com/labstack/echo"
)

type Prefix struct {
	Background string   `json:"background"`
	Color      string   `json:"color"`
	Words      []string `json:"words"`
	TimedEvent bool     `json:"timedEvent"`
	Default    bool     `json:"default"`
}

var DefaultPrefixes = []Prefix{
	Prefix{
		Background: "4C6C9B",
		Color:      "FFFFFF",
		Words:      []string{"HW", "Read", "Reading"},
		Default:    true,
	},
	Prefix{
		Background: "9ACD32",
		Color:      "FFFFFF",
		Words:      []string{"Project"},
		Default:    true,
	},
	Prefix{
		Background: "C3A528",
		Color:      "FFFFFF",
		Words:      []string{"Report", "Essay", "Paper", "Write"},
		Default:    true,
	},
	Prefix{
		Background: "FFA500",
		Color:      "FFFFFF",
		Words:      []string{"Quiz", "PopQuiz", "GradedHW", "GradedHomework"},
		Default:    true,
	},
	Prefix{
		Background: "DC143C",
		Color:      "FFFFFF",
		Words:      []string{"Test", "Final", "Exam", "Midterm", "Ahh"},
		Default:    true,
	},
	Prefix{
		Background: "2AC0F1",
		Color:      "FFFFFF",
		Words:      []string{"ICA", "FieldTrip", "Thingy"},
		Default:    true,
	},
	Prefix{
		Background: "2AF15E",
		Color:      "FFFFFF",
		Words:      []string{"Lab", "Study", "Memorize"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "003DAD",
		Color:      "FFFFFF",
		Words:      []string{"DocID"},
		Default:    true,
	},
	Prefix{
		Background: "000000",
		Color:      "00FF00",
		Words:      []string{"Trojun", "Hex"},
		Default:    true,
	},
	Prefix{
		Background: "5000BC",
		Color:      "FFFFFF",
		Words:      []string{"OptionalHW", "Challenge"},
		Default:    true,
	},
	Prefix{
		Background: "000099",
		Color:      "FFFFFF",
		Words:      []string{"Presentation", "Prez"},
		Default:    true,
	},
	Prefix{
		Background: "123456",
		Color:      "FFFFFF",
		Words:      []string{"BuildSession", "Build"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "5A1B87",
		Color:      "FFFFFF",
		Words:      []string{"Meeting", "Meet"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "01B501",
		Color:      "FFFFFF",
		Words:      []string{"Begin", "Start", "Do"},
		TimedEvent: true,
		Default:    true,
	},
	Prefix{
		Background: "E34000",
		Color:      "FFFFFF",
		Words:      []string{"Apply", "Application", "Deadline"},
		Default:    true,
	},
}

type PrefixesResponse struct {
	Status             string   `json:"status"`
	Prefixes           []Prefix `json:"prefixes"`
	FallbackBackground string   `json:"fallbackBackground"`
	FallbackColor      string   `json:"fallbackColor"`
}

func InitPrefixesAPI(e *echo.Echo) {
	e.GET("/prefixes/getDefaultList", func(c echo.Context) error {
		return c.JSON(http.StatusOK, PrefixesResponse{"ok", DefaultPrefixes, "FFD3BD", "000000"})
	})

	e.GET("/prefixes/getList", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}

		return c.JSON(http.StatusOK, PrefixesResponse{"ok", DefaultPrefixes, "FFD3BD", "000000"})
	})
}
<|endoftext|>


<commit_before>package sortseq

import (
    	"strings"
	. "github.com/BrianReallyMany/yomama/seq"
	"github.com/BrianReallyMany/yomama/seq/oligo"
)

type SeqSorter struct {
	primerMap map[[2]string]string
	barcodeMap map[[2]string]string
	linkers [][2]string
}

func NewSeqSorter(input string) (*SeqSorter, error) {
	lines := strings.Split(input, "\n")
	primerMap := make(map[[2]string]string)
	barcodeMap := make(map[[2]string]string)
	ok := oligo.ValidateOligoText(input)
	if !ok {
		return &SeqSorter{}, &oligo.OligoError{"Failed to validate oligo file\n"}
	}
	numLinkers := oligo.CountLinkers(input)
	linkers := make([][2]string, numLinkers)
	for _, line := range lines {
		if line == "" {
			continue
		}
		oligotype := oligo.OligoType(line)
		fields := strings.Split(line, "\t")
		switch oligotype {
		case "":
			continue
		case "barcode":
			oligoSeqs := [2]string{fields[1], fields[2]}
			oligoID := fields[3]
			barcodeMap[oligoSeqs] = oligoID
		case "primer":
			oligoSeqs := [2]string{fields[1], fields[2]}
			oligoID := fields[3]
			primerMap[oligoSeqs] = oligoID
		case "linker":
			linkers[len(linkers)-1] = [2]string{fields[1], fields[2]}
		}
	}
	sorter := &SeqSorter{primerMap, barcodeMap, linkers}
	return sorter, nil
}

func (s *SeqSorter) SortSeq(seq Seq) SortedSeq {
	// TODO
	seq.Bases = "gattaca"
	return SortedSeq{seq, SortKey{}}
}
<commit_msg>pseudocode for SortSeq<commit_after>package sortseq

import (
    	"strings"
	. "github.com/BrianReallyMany/yomama/seq"
	"github.com/BrianReallyMany/yomama/seq/oligo"
)

type SeqSorter struct {
	primerMap map[[2]string]string
	barcodeMap map[[2]string]string
	linkers [][2]string
}

func NewSeqSorter(input string) (*SeqSorter, error) {
	lines := strings.Split(input, "\n")
	primerMap := make(map[[2]string]string)
	barcodeMap := make(map[[2]string]string)
	ok := oligo.ValidateOligoText(input)
	if !ok {
		return &SeqSorter{}, &oligo.OligoError{"Failed to validate oligo file\n"}
	}
	numLinkers := oligo.CountLinkers(input)
	linkers := make([][2]string, numLinkers)
	for _, line := range lines {
		if line == "" {
			continue
		}
		oligotype := oligo.OligoType(line)
		fields := strings.Split(line, "\t")
		switch oligotype {
		case "":
			continue
		case "barcode":
			oligoSeqs := [2]string{fields[1], fields[2]}
			oligoID := fields[3]
			barcodeMap[oligoSeqs] = oligoID
		case "primer":
			oligoSeqs := [2]string{fields[1], fields[2]}
			oligoID := fields[3]
			primerMap[oligoSeqs] = oligoID
		case "linker":
			linkers[len(linkers)-1] = [2]string{fields[1], fields[2]}
		}
	}
	sorter := &SeqSorter{primerMap, barcodeMap, linkers}
	return sorter, nil
}

func (s *SeqSorter) SortSeq(seq Seq) SortedSeq {
	// Find barcode pair with best match
	// get sample name
	// trim barcodes off seq bases and qual scores

	// Find linker pair with best match
	// trim linkers off seq bases and qual scores

	// Find primer pair with best match
	// get sample name
	// trim primers off seq bases and qual scores

	// Make SortKey
	// Make SortedSeq
	// Return it.
	seq.Bases = "gattaca"
	return SortedSeq{seq, SortKey{}}
}
<|endoftext|>


<commit_before>package lfs

import (
	"bufio"
	"bytes"
	"io"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/rubyist/tracerx"
)

const (
	// blobSizeCutoff is used to determine which files to scan for Git LFS
	// pointers.  Any file with a size below this cutoff will be scanned.
	blobSizeCutoff = 140

	// stdoutBufSize is the size of the buffers given to a sub-process stdout
	stdoutBufSize = 16384

	// chanBufSize is the size of the channels used to pass data from one
	// sub-process to another.
	chanBufSize = 100
)

// wrappedPointer wraps a pointer.Pointer and provides the git sha1
// and the file name associated with the object, taken from the
// rev-list output.
type wrappedPointer struct {
	Sha1    string
	Name    string
	SrcName string
	Size    int64
	Status  string
	*Pointer
}

// indexFile is used when scanning the index. It stores the name of
// the file, the status of the file in the index, and, in the case of
// a moved or copied file, the original name of the file.
type indexFile struct {
	Name    string
	SrcName string
	Status  string
}

var z40 = regexp.MustCompile(`\^?0{40}`)

// ScanRefs takes a ref and returns a slice of wrappedPointer objects
// for all Git LFS pointers it finds for that ref.
func ScanRefs(refLeft, refRight string) ([]*wrappedPointer, error) {
	nameMap := make(map[string]string, 0)
	start := time.Now()

	revs, err := revListShas(refLeft, refRight, refLeft == "", nameMap)
	if err != nil {
		return nil, err
	}

	smallShas, err := catFileBatchCheck(revs)
	if err != nil {
		return nil, err
	}

	pointerc, err := catFileBatch(smallShas)
	if err != nil {
		return nil, err
	}

	pointers := make([]*wrappedPointer, 0)
	for p := range pointerc {
		if name, ok := nameMap[p.Sha1]; ok {
			p.Name = name
		}
		pointers = append(pointers, p)
	}

	tracerx.PerformanceSince("scan", start)

	return pointers, nil
}

// ScanIndex returns a slice of wrappedPointer objects for all
// Git LFS pointers it finds in the index.
func ScanIndex() ([]*wrappedPointer, error) {
	nameMap := make(map[string]*indexFile, 0)
	start := time.Now()

	revs, err := revListIndex(false, nameMap)
	if err != nil {
		return nil, err
	}

	cachedRevs, err := revListIndex(true, nameMap)
	if err != nil {
		return nil, err
	}

	allRevs := make(chan string)
	go func() {
		seenRevs := make(map[string]bool, 0)

		for rev := range revs {
			seenRevs[rev] = true
			allRevs <- rev
		}

		for rev := range cachedRevs {
			if _, ok := seenRevs[rev]; !ok {
				allRevs <- rev
			}
		}
		close(allRevs)
	}()

	smallShas, err := catFileBatchCheck(allRevs)
	if err != nil {
		return nil, err
	}

	pointerc, err := catFileBatch(smallShas)
	if err != nil {
		return nil, err
	}

	pointers := make([]*wrappedPointer, 0)
	for p := range pointerc {
		if e, ok := nameMap[p.Sha1]; ok {
			p.Name = e.Name
			p.Status = e.Status
			p.SrcName = e.SrcName
		}
		pointers = append(pointers, p)
	}

	tracerx.PerformanceSince("scan-staging", start)

	return pointers, nil

}

// revListShas uses git rev-list to return the list of object sha1s
// for the given ref. If all is true, ref is ignored. It returns a
// channel from which sha1 strings can be read.
func revListShas(refLeft, refRight string, all bool, nameMap map[string]string) (chan string, error) {
	refArgs := []string{"rev-list", "--objects"}
	if all {
		refArgs = append(refArgs, "--all")
	} else {
		refArgs = append(refArgs, "--no-walk")
		refArgs = append(refArgs, refLeft)
		if refRight != "" && !z40.MatchString(refRight) {
			refArgs = append(refArgs, refRight)
		}
	}

	cmd, err := startCommand("git", refArgs...)
	if err != nil {
		return nil, err
	}

	cmd.Stdin.Close()

	revs := make(chan string, chanBufSize)

	go func() {
		scanner := bufio.NewScanner(cmd.Stdout)
		for scanner.Scan() {
			line := strings.TrimSpace(scanner.Text())
			if len(line) < 40 {
				continue
			}

			sha1 := line[0:40]
			if len(line) > 40 {
				nameMap[sha1] = line[41:len(line)]
			}
			revs <- sha1
		}
		close(revs)
	}()

	return revs, nil
}

// revListIndex uses git diff-index to return the list of object sha1s
// for in the indexf. It returns a channel from which sha1 strings can be read.
// The namMap will be filled indexFile pointers mapping sha1s to indexFiles.
func revListIndex(cache bool, nameMap map[string]*indexFile) (chan string, error) {
	cmdArgs := []string{"diff-index", "-M"}
	if cache {
		cmdArgs = append(cmdArgs, "--cached")
	}
	cmdArgs = append(cmdArgs, "HEAD")

	cmd, err := startCommand("git", cmdArgs...)
	if err != nil {
		return nil, err
	}

	cmd.Stdin.Close()

	revs := make(chan string, chanBufSize)

	go func() {
		scanner := bufio.NewScanner(cmd.Stdout)
		for scanner.Scan() {
			// Format is:
			// :100644 100644 c5b3d83a7542255ec7856487baa5e83d65b1624c 9e82ac1b514be060945392291b5b3108c22f6fe3 M foo.gif
			// :<old mode> <new mode> <old sha1> <new sha1> <status>\t<file name>[\t<file name>]
			line := scanner.Text()
			parts := strings.Split(line, "\t")
			if len(parts) < 2 {
				continue
			}

			description := strings.Split(parts[0], " ")
			files := parts[1:len(parts)]

			if len(description) >= 5 {
				status := description[4][0:1]
				sha1 := description[3]
				if status == "M" {
					sha1 = description[2] // This one is modified but not added
				}
				nameMap[sha1] = &indexFile{files[len(files)-1], files[0], status}
				revs <- sha1
			}
		}
		close(revs)
	}()

	return revs, nil
}

// catFileBatchCheck uses git cat-file --batch-check to get the type
// and size of a git object. Any object that isn't of type blob and
// under the blobSizeCutoff will be ignored. revs is a channel over
// which strings containing git sha1s will be sent. It returns a channel
// from which sha1 strings can be read.
func catFileBatchCheck(revs chan string) (chan string, error) {
	cmd, err := startCommand("git", "cat-file", "--batch-check")
	if err != nil {
		return nil, err
	}

	smallRevs := make(chan string, chanBufSize)

	go func() {
		scanner := bufio.NewScanner(cmd.Stdout)
		for scanner.Scan() {
			line := scanner.Text()
			// Format is:
			// <sha1> <type> <size>
			// type is at a fixed spot, if we see that it's "blob", we can avoid
			// splitting the line just to get the size.
			if line[41:45] == "blob" {
				size, err := strconv.Atoi(line[46:len(line)])
				if err != nil {
					continue
				}
				if size < blobSizeCutoff {
					smallRevs <- line[0:40]
				}
			}
		}
		close(smallRevs)
	}()

	go func() {
		for r := range revs {
			cmd.Stdin.Write([]byte(r + "\n"))
		}
		cmd.Stdin.Close()
	}()

	return smallRevs, nil
}

// catFileBatch uses git cat-file --batch to get the object contents
// of a git object, given its sha1. The contents will be decoded into
// a Git LFS pointer. revs is a channel over which strings containing Git SHA1s
// will be sent. It returns a channel from which point.Pointers can be read.
func catFileBatch(revs chan string) (chan *wrappedPointer, error) {
	cmd, err := startCommand("git", "cat-file", "--batch")
	if err != nil {
		return nil, err
	}

	pointers := make(chan *wrappedPointer, chanBufSize)

	go func() {
		for {
			l, err := cmd.Stdout.ReadBytes('\n')
			if err != nil {
				break
			}

			// Line is formatted:
			// <sha1> <type> <size>
			fields := bytes.Fields(l)
			s, _ := strconv.Atoi(string(fields[2]))

			nbuf := make([]byte, s)
			_, err = io.ReadFull(cmd.Stdout, nbuf)
			if err != nil {
				break // Legit errors
			}

			p, err := DecodePointer(bytes.NewBuffer(nbuf))
			if err == nil {
				pointers <- &wrappedPointer{
					Sha1:    string(fields[0]),
					Size:    p.Size,
					Pointer: p,
				}
			}

			_, err = cmd.Stdout.ReadBytes('\n') // Extra \n inserted by cat-file
			if err != nil {
				break
			}
		}
		close(pointers)
	}()

	go func() {
		for r := range revs {
			cmd.Stdin.Write([]byte(r + "\n"))
		}
		cmd.Stdin.Close()
	}()

	return pointers, nil
}

type wrappedCmd struct {
	Stdin  io.WriteCloser
	Stdout *bufio.Reader
	*exec.Cmd
}

// startCommand starts up a command and creates a stdin pipe and a buffered
// stdout pipe, wrapped in a wrappedCmd. The stdout buffer will be of stdoutBufSize
// bytes.
func startCommand(command string, args ...string) (*wrappedCmd, error) {
	cmd := exec.Command(command, args...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return nil, err
	}

	tracerx.Printf("run_command: %s %s", command, strings.Join(args, " "))
	if err := cmd.Start(); err != nil {
		return nil, err
	}

	return &wrappedCmd{stdin, bufio.NewReaderSize(stdout, stdoutBufSize), cmd}, nil
}
<commit_msg>ラララララ ラー ウウウ フフフ<commit_after>package lfs

import (
	"bufio"
	"bytes"
	"io"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/rubyist/tracerx"
)

const (
	// blobSizeCutoff is used to determine which files to scan for Git LFS
	// pointers.  Any file with a size below this cutoff will be scanned.
	blobSizeCutoff = 140

	// stdoutBufSize is the size of the buffers given to a sub-process stdout
	stdoutBufSize = 16384

	// chanBufSize is the size of the channels used to pass data from one
	// sub-process to another.
	chanBufSize = 100
)

// wrappedPointer wraps a pointer.Pointer and provides the git sha1
// and the file name associated with the object, taken from the
// rev-list output.
type wrappedPointer struct {
	Sha1    string
	Name    string
	SrcName string
	Size    int64
	Status  string
	*Pointer
}

// indexFile is used when scanning the index. It stores the name of
// the file, the status of the file in the index, and, in the case of
// a moved or copied file, the original name of the file.
type indexFile struct {
	Name    string
	SrcName string
	Status  string
}

var z40 = regexp.MustCompile(`\^?0{40}`)

// ScanRefs takes a ref and returns a slice of wrappedPointer objects
// for all Git LFS pointers it finds for that ref.
func ScanRefs(refLeft, refRight string) ([]*wrappedPointer, error) {
	nameMap := make(map[string]string, 0)

	start := time.Now()
	defer func() {
		tracerx.PerformanceSince("scan", start)
	}()

	revs, err := revListShas(refLeft, refRight, refLeft == "", nameMap)
	if err != nil {
		return nil, err
	}

	smallShas, err := catFileBatchCheck(revs)
	if err != nil {
		return nil, err
	}

	pointerc, err := catFileBatch(smallShas)
	if err != nil {
		return nil, err
	}

	pointers := make([]*wrappedPointer, 0)
	for p := range pointerc {
		if name, ok := nameMap[p.Sha1]; ok {
			p.Name = name
		}
		pointers = append(pointers, p)
	}

	return pointers, nil
}

// ScanIndex returns a slice of wrappedPointer objects for all
// Git LFS pointers it finds in the index.
func ScanIndex() ([]*wrappedPointer, error) {
	nameMap := make(map[string]*indexFile, 0)

	start := time.Now()
	defer func() {
		tracerx.PerformanceSince("scan-staging", start)
	}()

	revs, err := revListIndex(false, nameMap)
	if err != nil {
		return nil, err
	}

	cachedRevs, err := revListIndex(true, nameMap)
	if err != nil {
		return nil, err
	}

	allRevs := make(chan string)
	go func() {
		seenRevs := make(map[string]bool, 0)

		for rev := range revs {
			seenRevs[rev] = true
			allRevs <- rev
		}

		for rev := range cachedRevs {
			if _, ok := seenRevs[rev]; !ok {
				allRevs <- rev
			}
		}
		close(allRevs)
	}()

	smallShas, err := catFileBatchCheck(allRevs)
	if err != nil {
		return nil, err
	}

	pointerc, err := catFileBatch(smallShas)
	if err != nil {
		return nil, err
	}

	pointers := make([]*wrappedPointer, 0)
	for p := range pointerc {
		if e, ok := nameMap[p.Sha1]; ok {
			p.Name = e.Name
			p.Status = e.Status
			p.SrcName = e.SrcName
		}
		pointers = append(pointers, p)
	}

	return pointers, nil

}

// revListShas uses git rev-list to return the list of object sha1s
// for the given ref. If all is true, ref is ignored. It returns a
// channel from which sha1 strings can be read.
func revListShas(refLeft, refRight string, all bool, nameMap map[string]string) (chan string, error) {
	refArgs := []string{"rev-list", "--objects"}
	if all {
		refArgs = append(refArgs, "--all")
	} else {
		refArgs = append(refArgs, "--no-walk")
		refArgs = append(refArgs, refLeft)
		if refRight != "" && !z40.MatchString(refRight) {
			refArgs = append(refArgs, refRight)
		}
	}

	cmd, err := startCommand("git", refArgs...)
	if err != nil {
		return nil, err
	}

	cmd.Stdin.Close()

	revs := make(chan string, chanBufSize)

	go func() {
		scanner := bufio.NewScanner(cmd.Stdout)
		for scanner.Scan() {
			line := strings.TrimSpace(scanner.Text())
			if len(line) < 40 {
				continue
			}

			sha1 := line[0:40]
			if len(line) > 40 {
				nameMap[sha1] = line[41:len(line)]
			}
			revs <- sha1
		}
		close(revs)
	}()

	return revs, nil
}

// revListIndex uses git diff-index to return the list of object sha1s
// for in the indexf. It returns a channel from which sha1 strings can be read.
// The namMap will be filled indexFile pointers mapping sha1s to indexFiles.
func revListIndex(cache bool, nameMap map[string]*indexFile) (chan string, error) {
	cmdArgs := []string{"diff-index", "-M"}
	if cache {
		cmdArgs = append(cmdArgs, "--cached")
	}
	cmdArgs = append(cmdArgs, "HEAD")

	cmd, err := startCommand("git", cmdArgs...)
	if err != nil {
		return nil, err
	}

	cmd.Stdin.Close()

	revs := make(chan string, chanBufSize)

	go func() {
		scanner := bufio.NewScanner(cmd.Stdout)
		for scanner.Scan() {
			// Format is:
			// :100644 100644 c5b3d83a7542255ec7856487baa5e83d65b1624c 9e82ac1b514be060945392291b5b3108c22f6fe3 M foo.gif
			// :<old mode> <new mode> <old sha1> <new sha1> <status>\t<file name>[\t<file name>]
			line := scanner.Text()
			parts := strings.Split(line, "\t")
			if len(parts) < 2 {
				continue
			}

			description := strings.Split(parts[0], " ")
			files := parts[1:len(parts)]

			if len(description) >= 5 {
				status := description[4][0:1]
				sha1 := description[3]
				if status == "M" {
					sha1 = description[2] // This one is modified but not added
				}
				nameMap[sha1] = &indexFile{files[len(files)-1], files[0], status}
				revs <- sha1
			}
		}
		close(revs)
	}()

	return revs, nil
}

// catFileBatchCheck uses git cat-file --batch-check to get the type
// and size of a git object. Any object that isn't of type blob and
// under the blobSizeCutoff will be ignored. revs is a channel over
// which strings containing git sha1s will be sent. It returns a channel
// from which sha1 strings can be read.
func catFileBatchCheck(revs chan string) (chan string, error) {
	cmd, err := startCommand("git", "cat-file", "--batch-check")
	if err != nil {
		return nil, err
	}

	smallRevs := make(chan string, chanBufSize)

	go func() {
		scanner := bufio.NewScanner(cmd.Stdout)
		for scanner.Scan() {
			line := scanner.Text()
			// Format is:
			// <sha1> <type> <size>
			// type is at a fixed spot, if we see that it's "blob", we can avoid
			// splitting the line just to get the size.
			if line[41:45] == "blob" {
				size, err := strconv.Atoi(line[46:len(line)])
				if err != nil {
					continue
				}
				if size < blobSizeCutoff {
					smallRevs <- line[0:40]
				}
			}
		}
		close(smallRevs)
	}()

	go func() {
		for r := range revs {
			cmd.Stdin.Write([]byte(r + "\n"))
		}
		cmd.Stdin.Close()
	}()

	return smallRevs, nil
}

// catFileBatch uses git cat-file --batch to get the object contents
// of a git object, given its sha1. The contents will be decoded into
// a Git LFS pointer. revs is a channel over which strings containing Git SHA1s
// will be sent. It returns a channel from which point.Pointers can be read.
func catFileBatch(revs chan string) (chan *wrappedPointer, error) {
	cmd, err := startCommand("git", "cat-file", "--batch")
	if err != nil {
		return nil, err
	}

	pointers := make(chan *wrappedPointer, chanBufSize)

	go func() {
		for {
			l, err := cmd.Stdout.ReadBytes('\n')
			if err != nil {
				break
			}

			// Line is formatted:
			// <sha1> <type> <size>
			fields := bytes.Fields(l)
			s, _ := strconv.Atoi(string(fields[2]))

			nbuf := make([]byte, s)
			_, err = io.ReadFull(cmd.Stdout, nbuf)
			if err != nil {
				break // Legit errors
			}

			p, err := DecodePointer(bytes.NewBuffer(nbuf))
			if err == nil {
				pointers <- &wrappedPointer{
					Sha1:    string(fields[0]),
					Size:    p.Size,
					Pointer: p,
				}
			}

			_, err = cmd.Stdout.ReadBytes('\n') // Extra \n inserted by cat-file
			if err != nil {
				break
			}
		}
		close(pointers)
	}()

	go func() {
		for r := range revs {
			cmd.Stdin.Write([]byte(r + "\n"))
		}
		cmd.Stdin.Close()
	}()

	return pointers, nil
}

type wrappedCmd struct {
	Stdin  io.WriteCloser
	Stdout *bufio.Reader
	*exec.Cmd
}

// startCommand starts up a command and creates a stdin pipe and a buffered
// stdout pipe, wrapped in a wrappedCmd. The stdout buffer will be of stdoutBufSize
// bytes.
func startCommand(command string, args ...string) (*wrappedCmd, error) {
	cmd := exec.Command(command, args...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return nil, err
	}

	tracerx.Printf("run_command: %s %s", command, strings.Join(args, " "))
	if err := cmd.Start(); err != nil {
		return nil, err
	}

	return &wrappedCmd{stdin, bufio.NewReaderSize(stdout, stdoutBufSize), cmd}, nil
}
<|endoftext|>


<commit_before>package brightbox

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/brightbox/gobrightbox"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceBrightboxLoadBalancer() *schema.Resource {
	return &schema.Resource{
		Create: resourceBrightboxLoadBalancerCreate,
		Read:   resourceBrightboxLoadBalancerRead,
		Update: resourceBrightboxLoadBalancerUpdate,
		Delete: resourceBrightboxLoadBalancerDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(defaultTimeout),
			Delete: schema.DefaultTimeout(defaultTimeout),
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"policy": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"certificate_pem": {
				Type:      schema.TypeString,
				Optional:  true,
				StateFunc: hash_string,
			},
			"certificate_private_key": {
				Type:      schema.TypeString,
				Optional:  true,
				StateFunc: hash_string,
			},
			"sslv3": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"status": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"locked": {
				Type:     schema.TypeBool,
				Computed: true,
			},
			"buffer_size": {
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"nodes": {
				Type:     schema.TypeSet,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
				Computed: true,
				Set:      schema.HashString,
			},
			"listener": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"protocol": {
							Type:     schema.TypeString,
							Required: true,
						},
						"in": {
							Type:     schema.TypeInt,
							Required: true,
						},

						"out": {
							Type:     schema.TypeInt,
							Required: true,
						},

						"timeout": {
							Type:     schema.TypeInt,
							Optional: true,
							Default:  50000,
						},
					},
				},
				Set: resourceBrightboxLbListenerHash,
			},
			"healthcheck": {
				Type:     schema.TypeList,
				MaxItems: 1,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"type": {
							Type:     schema.TypeString,
							Required: true,
						},
						"port": {
							Type:     schema.TypeInt,
							Required: true,
						},
						"request": {
							Type:     schema.TypeString,
							Optional: true,
							Computed: true,
						},
						"interval": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"timeout": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"threshold_up": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"threshold_down": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
					},
				},
			},
		},
	}
}

func resourceBrightboxLbListenerHash(
	v interface{},
) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	buf.WriteString(fmt.Sprintf("%d-", m["in"].(int)))
	buf.WriteString(fmt.Sprintf("%s-",
		strings.ToLower(m["protocol"].(string))))
	buf.WriteString(fmt.Sprintf("%d-", m["out"].(int)))
	buf.WriteString(fmt.Sprintf("%d-", m["timeout"].(int)))

	return hashcode.String(buf.String())
}

func setLoadBalancerAttributes(
	d *schema.ResourceData,
	load_balancer *brightbox.LoadBalancer,
) error {
	d.Set("name", load_balancer.Name)
	d.Set("status", load_balancer.Status)
	d.Set("locked", load_balancer.Locked)
	d.Set("policy", load_balancer.Policy)
	d.Set("buffer_size", load_balancer.BufferSize)

	nodeIds := make([]string, 0, len(load_balancer.Nodes))
	for _, node := range load_balancer.Nodes {
		nodeIds = append(nodeIds, node.Id)
	}
	d.Set("nodes", nodeIds)

	cipIds := make([]string, 0, len(load_balancer.CloudIPs))
	for _, cip := range load_balancer.CloudIPs {
		cipIds = append(cipIds, cip.Id)
	}
	d.Set("cloud_ips", cipIds)

	listeners := make([]map[string]interface{}, 0, len(load_balancer.Listeners))
	for _, listener := range load_balancer.Listeners {
		l := map[string]interface{}{
			"protocol": listener.Protocol,
			"in":       listener.In,
			"out":      listener.Out,
			"timeout":  listener.Timeout,
		}

		listeners = append(listeners, l)
	}
	d.Set("listener", listeners)
	log.Printf("[DEBUG] Healthcheck details are %#v", load_balancer.Healthcheck)
	healthchecks := make([]map[string]interface{}, 0, 1)
	chk := map[string]interface{}{
		"type":           load_balancer.Healthcheck.Type,
		"port":           load_balancer.Healthcheck.Port,
		"request":        load_balancer.Healthcheck.Request,
		"interval":       load_balancer.Healthcheck.Interval,
		"timeout":        load_balancer.Healthcheck.Timeout,
		"threshold_up":   load_balancer.Healthcheck.ThresholdUp,
		"threshold_down": load_balancer.Healthcheck.ThresholdDown,
	}
	healthchecks = append(healthchecks, chk)
	d.Set("healthcheck", healthchecks)
	log.Printf("[DEBUG] Certificate details are %#v", load_balancer.Certificate)
	if load_balancer.Certificate == nil {
		d.Set("sslv3", false)
	} else {
		d.Set("sslv3", load_balancer.Certificate.SslV3)
	}
	return nil
}

func loadBalancerStateRefresh(client *brightbox.Client, loadBalancerID string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		loadBalancer, err := client.LoadBalancer(loadBalancerID)
		if err != nil {
			log.Printf("Error on Load Balancer State Refresh: %s", err)
			return nil, "", err
		}
		return loadBalancer, loadBalancer.Status, nil
	}
}

func resourceBrightboxLoadBalancerCreate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer create called")
	load_balancer_opts := &brightbox.LoadBalancerOptions{}

	err := addUpdateableLoadBalancerOptions(d, load_balancer_opts)
	if err != nil {
		return err
	}

	log.Printf("[DEBUG] Load Balancer create configuration %#v", load_balancer_opts)
	output_load_balancer_options(load_balancer_opts)

	load_balancer, err := client.CreateLoadBalancer(load_balancer_opts)
	if err != nil {
		return fmt.Errorf("Error creating server: %s", err)
	}

	d.SetId(load_balancer.Id)

	log.Printf("[INFO] Waiting for Load Balancer (%s) to become available", d.Id())

	stateConf := resource.StateChangeConf{
		Pending:    []string{"creating"},
		Target:     []string{"active"},
		Refresh:    loadBalancerStateRefresh(client, load_balancer.Id),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		Delay:      checkDelay,
		MinTimeout: minimumRefreshWait,
	}
	active_load_balancer, err := stateConf.WaitForState()
	if err != nil {
		return err
	}

	return setLoadBalancerAttributes(d, active_load_balancer.(*brightbox.LoadBalancer))
}

func resourceBrightboxLoadBalancerRead(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer read called for %s", d.Id())
	load_balancer, err := client.LoadBalancer(d.Id())
	if err != nil {
		return fmt.Errorf("Error retrieving Load Balancer details: %s", err)
	}
	if load_balancer.Status == "deleted" {
		log.Printf("[WARN] Load Balancer not found, removing from state: %s", d.Id())
		d.SetId("")
		return nil
	}

	return setLoadBalancerAttributes(d, load_balancer)
}

func resourceBrightboxLoadBalancerUpdate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer update called for %s", d.Id())
	load_balancer_opts := &brightbox.LoadBalancerOptions{
		Id: d.Id(),
	}

	err := addUpdateableLoadBalancerOptions(d, load_balancer_opts)
	if err != nil {
		return err
	}

	log.Printf("[DEBUG] Load Balancer update configuration %#v", load_balancer_opts)
	output_load_balancer_options(load_balancer_opts)

	load_balancer, err := client.UpdateLoadBalancer(load_balancer_opts)
	if err != nil {
		return fmt.Errorf("Error updating load_balancer: %s", err)
	}

	return setLoadBalancerAttributes(d, load_balancer)
}

func resourceBrightboxLoadBalancerDelete(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer delete called for %s", d.Id())
	err := client.DestroyLoadBalancer(d.Id())
	if err != nil {
		return fmt.Errorf("Error deleting Load Balancer: %s", err)
	}
	stateConf := resource.StateChangeConf{
		Pending:    []string{"deleting", "active"},
		Target:     []string{"deleted"},
		Refresh:    loadBalancerStateRefresh(client, d.Id()),
		Timeout:    d.Timeout(schema.TimeoutDelete),
		Delay:      checkDelay,
		MinTimeout: minimumRefreshWait,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}
	return nil
}

func addUpdateableLoadBalancerOptions(
	d *schema.ResourceData,
	opts *brightbox.LoadBalancerOptions,
) error {

	assign_string(d, &opts.Name, "name")
	assign_string(d, &opts.Policy, "policy")
	assign_string(d, &opts.CertificatePem, "certificate_pem")
	assign_string(d, &opts.CertificatePrivateKey, "certificate_private_key")
	assign_int(d, &opts.BufferSize, "buffer_size")
	assign_bool(d, &opts.SslV3, "sslv3")
	assign_listeners(d, &opts.Listeners)
	assign_nodes(d, &opts.Nodes)
	return assign_healthcheck(d, &opts.Healthcheck)
}

func assign_healthcheck(d *schema.ResourceData, target **brightbox.LoadBalancerHealthcheck) error {
	if d.HasChange("healthcheck") {
		hc := d.Get("healthcheck").([]interface{})
		check := hc[0].(map[string]interface{})
		temp := brightbox.LoadBalancerHealthcheck{
			Type: check["type"].(string),
			Port: check["port"].(int),
		}
		if attr, ok := check["request"]; ok {
			temp.Request = attr.(string)
		}
		if attr, ok := check["interval"]; ok {
			temp.Interval = attr.(int)
		}
		if attr, ok := check["timeout"]; ok {
			temp.Timeout = attr.(int)
		}
		if attr, ok := check["threshold_up"]; ok {
			temp.ThresholdUp = attr.(int)
		}
		if attr, ok := check["threshold_down"]; ok {
			temp.ThresholdDown = attr.(int)
		}
		*target = &temp
	}
	return nil
}

func assign_listeners(d *schema.ResourceData, target *[]brightbox.LoadBalancerListener) {
	if d.HasChange("listener") {
		*target = expandListeners(d.Get("listener").(*schema.Set).List())
	}
}

func assign_nodes(d *schema.ResourceData, target *[]brightbox.LoadBalancerNode) {
	if d.HasChange("nodes") {
		*target = expandNodes(d.Get("nodes").(*schema.Set).List())
	}
}

func expandListeners(configured []interface{}) []brightbox.LoadBalancerListener {
	listeners := make([]brightbox.LoadBalancerListener, len(configured))

	for i, listen_source := range configured {
		data := listen_source.(map[string]interface{})
		listeners[i].Protocol = data["protocol"].(string)
		listeners[i].In = data["in"].(int)
		listeners[i].Out = data["out"].(int)
		if attr, ok := data["timeout"]; ok {
			listeners[i].Timeout = attr.(int)
		}
	}
	return listeners
}

func expandNodes(configured []interface{}) []brightbox.LoadBalancerNode {
	nodes := make([]brightbox.LoadBalancerNode, len(configured))

	for i, data := range configured {
		nodes[i].Node = data.(string)
	}
	return nodes
}

func output_load_balancer_options(opts *brightbox.LoadBalancerOptions) {
	if opts.Name != nil {
		log.Printf("[DEBUG] Load Balancer Name %v", *opts.Name)
	}
	if opts.Nodes != nil {
		log.Printf("[DEBUG] Load Balancer Nodes %#v", opts.Nodes)
	}
	if opts.Policy != nil {
		log.Printf("[DEBUG] Load Balancer Policy %v", *opts.Policy)
	}
	if opts.BufferSize != nil {
		log.Printf("[DEBUG] Load Balancer BufferSize %v", *opts.BufferSize)
	}
	if opts.Listeners != nil {
		log.Printf("[DEBUG] Load Balancer Listeners %#v", opts.Listeners)
	}
	if opts.Healthcheck != nil {
		log.Printf("[DEBUG] Load Balancer Healthcheck %#v", *opts.Healthcheck)
	}
	if opts.CertificatePem != nil {
		log.Printf("[DEBUG] Load Balancer CertificatePem %v", *opts.CertificatePem)
	}
	if opts.CertificatePrivateKey != nil {
		log.Printf("[DEBUG] Load Balancer CertificatePrivateKey %v", *opts.CertificatePrivateKey)
	}
	if opts.SslV3 != nil {
		log.Printf("[DEBUG] Load Balancer SslV3 %v", *opts.SslV3)
	}
}
<commit_msg>Remove unnecessary append in load balancer code<commit_after>package brightbox

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/brightbox/gobrightbox"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceBrightboxLoadBalancer() *schema.Resource {
	return &schema.Resource{
		Create: resourceBrightboxLoadBalancerCreate,
		Read:   resourceBrightboxLoadBalancerRead,
		Update: resourceBrightboxLoadBalancerUpdate,
		Delete: resourceBrightboxLoadBalancerDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(defaultTimeout),
			Delete: schema.DefaultTimeout(defaultTimeout),
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"policy": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"certificate_pem": {
				Type:      schema.TypeString,
				Optional:  true,
				StateFunc: hash_string,
			},
			"certificate_private_key": {
				Type:      schema.TypeString,
				Optional:  true,
				StateFunc: hash_string,
			},
			"sslv3": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"status": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"locked": {
				Type:     schema.TypeBool,
				Computed: true,
			},
			"buffer_size": {
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"nodes": {
				Type:     schema.TypeSet,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
				Computed: true,
				Set:      schema.HashString,
			},
			"listener": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"protocol": {
							Type:     schema.TypeString,
							Required: true,
						},
						"in": {
							Type:     schema.TypeInt,
							Required: true,
						},

						"out": {
							Type:     schema.TypeInt,
							Required: true,
						},

						"timeout": {
							Type:     schema.TypeInt,
							Optional: true,
							Default:  50000,
						},
					},
				},
				Set: resourceBrightboxLbListenerHash,
			},
			"healthcheck": {
				Type:     schema.TypeList,
				MaxItems: 1,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"type": {
							Type:     schema.TypeString,
							Required: true,
						},
						"port": {
							Type:     schema.TypeInt,
							Required: true,
						},
						"request": {
							Type:     schema.TypeString,
							Optional: true,
							Computed: true,
						},
						"interval": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"timeout": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"threshold_up": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"threshold_down": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
					},
				},
			},
		},
	}
}

func resourceBrightboxLbListenerHash(
	v interface{},
) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	buf.WriteString(fmt.Sprintf("%d-", m["in"].(int)))
	buf.WriteString(fmt.Sprintf("%s-",
		strings.ToLower(m["protocol"].(string))))
	buf.WriteString(fmt.Sprintf("%d-", m["out"].(int)))
	buf.WriteString(fmt.Sprintf("%d-", m["timeout"].(int)))

	return hashcode.String(buf.String())
}

func setLoadBalancerAttributes(
	d *schema.ResourceData,
	load_balancer *brightbox.LoadBalancer,
) error {
	d.Set("name", load_balancer.Name)
	d.Set("status", load_balancer.Status)
	d.Set("locked", load_balancer.Locked)
	d.Set("policy", load_balancer.Policy)
	d.Set("buffer_size", load_balancer.BufferSize)

	nodeIds := make([]string, 0, len(load_balancer.Nodes))
	for _, node := range load_balancer.Nodes {
		nodeIds = append(nodeIds, node.Id)
	}
	d.Set("nodes", nodeIds)

	cipIds := make([]string, 0, len(load_balancer.CloudIPs))
	for _, cip := range load_balancer.CloudIPs {
		cipIds = append(cipIds, cip.Id)
	}
	d.Set("cloud_ips", cipIds)

	listeners := make([]map[string]interface{}, len(load_balancer.Listeners))
	for i, listener := range load_balancer.Listeners {
		listeners[i] = map[string]interface{}{
			"protocol": listener.Protocol,
			"in":       listener.In,
			"out":      listener.Out,
			"timeout":  listener.Timeout,
		}
	}
	d.Set("listener", listeners)
	log.Printf("[DEBUG] Healthcheck details are %#v", load_balancer.Healthcheck)
	healthchecks := make([]map[string]interface{}, 0, 1)
	chk := map[string]interface{}{
		"type":           load_balancer.Healthcheck.Type,
		"port":           load_balancer.Healthcheck.Port,
		"request":        load_balancer.Healthcheck.Request,
		"interval":       load_balancer.Healthcheck.Interval,
		"timeout":        load_balancer.Healthcheck.Timeout,
		"threshold_up":   load_balancer.Healthcheck.ThresholdUp,
		"threshold_down": load_balancer.Healthcheck.ThresholdDown,
	}
	healthchecks = append(healthchecks, chk)
	d.Set("healthcheck", healthchecks)
	log.Printf("[DEBUG] Certificate details are %#v", load_balancer.Certificate)
	if load_balancer.Certificate == nil {
		d.Set("sslv3", false)
	} else {
		d.Set("sslv3", load_balancer.Certificate.SslV3)
	}
	return nil
}

func loadBalancerStateRefresh(client *brightbox.Client, loadBalancerID string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		loadBalancer, err := client.LoadBalancer(loadBalancerID)
		if err != nil {
			log.Printf("Error on Load Balancer State Refresh: %s", err)
			return nil, "", err
		}
		return loadBalancer, loadBalancer.Status, nil
	}
}

func resourceBrightboxLoadBalancerCreate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer create called")
	load_balancer_opts := &brightbox.LoadBalancerOptions{}

	err := addUpdateableLoadBalancerOptions(d, load_balancer_opts)
	if err != nil {
		return err
	}

	log.Printf("[DEBUG] Load Balancer create configuration %#v", load_balancer_opts)
	output_load_balancer_options(load_balancer_opts)

	load_balancer, err := client.CreateLoadBalancer(load_balancer_opts)
	if err != nil {
		return fmt.Errorf("Error creating server: %s", err)
	}

	d.SetId(load_balancer.Id)

	log.Printf("[INFO] Waiting for Load Balancer (%s) to become available", d.Id())

	stateConf := resource.StateChangeConf{
		Pending:    []string{"creating"},
		Target:     []string{"active"},
		Refresh:    loadBalancerStateRefresh(client, load_balancer.Id),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		Delay:      checkDelay,
		MinTimeout: minimumRefreshWait,
	}
	active_load_balancer, err := stateConf.WaitForState()
	if err != nil {
		return err
	}

	return setLoadBalancerAttributes(d, active_load_balancer.(*brightbox.LoadBalancer))
}

func resourceBrightboxLoadBalancerRead(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer read called for %s", d.Id())
	load_balancer, err := client.LoadBalancer(d.Id())
	if err != nil {
		return fmt.Errorf("Error retrieving Load Balancer details: %s", err)
	}
	if load_balancer.Status == "deleted" {
		log.Printf("[WARN] Load Balancer not found, removing from state: %s", d.Id())
		d.SetId("")
		return nil
	}

	return setLoadBalancerAttributes(d, load_balancer)
}

func resourceBrightboxLoadBalancerUpdate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer update called for %s", d.Id())
	load_balancer_opts := &brightbox.LoadBalancerOptions{
		Id: d.Id(),
	}

	err := addUpdateableLoadBalancerOptions(d, load_balancer_opts)
	if err != nil {
		return err
	}

	log.Printf("[DEBUG] Load Balancer update configuration %#v", load_balancer_opts)
	output_load_balancer_options(load_balancer_opts)

	load_balancer, err := client.UpdateLoadBalancer(load_balancer_opts)
	if err != nil {
		return fmt.Errorf("Error updating load_balancer: %s", err)
	}

	return setLoadBalancerAttributes(d, load_balancer)
}

func resourceBrightboxLoadBalancerDelete(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[DEBUG] Load Balancer delete called for %s", d.Id())
	err := client.DestroyLoadBalancer(d.Id())
	if err != nil {
		return fmt.Errorf("Error deleting Load Balancer: %s", err)
	}
	stateConf := resource.StateChangeConf{
		Pending:    []string{"deleting", "active"},
		Target:     []string{"deleted"},
		Refresh:    loadBalancerStateRefresh(client, d.Id()),
		Timeout:    d.Timeout(schema.TimeoutDelete),
		Delay:      checkDelay,
		MinTimeout: minimumRefreshWait,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}
	return nil
}

func addUpdateableLoadBalancerOptions(
	d *schema.ResourceData,
	opts *brightbox.LoadBalancerOptions,
) error {

	assign_string(d, &opts.Name, "name")
	assign_string(d, &opts.Policy, "policy")
	assign_string(d, &opts.CertificatePem, "certificate_pem")
	assign_string(d, &opts.CertificatePrivateKey, "certificate_private_key")
	assign_int(d, &opts.BufferSize, "buffer_size")
	assign_bool(d, &opts.SslV3, "sslv3")
	assign_listeners(d, &opts.Listeners)
	assign_nodes(d, &opts.Nodes)
	return assign_healthcheck(d, &opts.Healthcheck)
}

func assign_healthcheck(d *schema.ResourceData, target **brightbox.LoadBalancerHealthcheck) error {
	if d.HasChange("healthcheck") {
		hc := d.Get("healthcheck").([]interface{})
		check := hc[0].(map[string]interface{})
		temp := brightbox.LoadBalancerHealthcheck{
			Type: check["type"].(string),
			Port: check["port"].(int),
		}
		if attr, ok := check["request"]; ok {
			temp.Request = attr.(string)
		}
		if attr, ok := check["interval"]; ok {
			temp.Interval = attr.(int)
		}
		if attr, ok := check["timeout"]; ok {
			temp.Timeout = attr.(int)
		}
		if attr, ok := check["threshold_up"]; ok {
			temp.ThresholdUp = attr.(int)
		}
		if attr, ok := check["threshold_down"]; ok {
			temp.ThresholdDown = attr.(int)
		}
		*target = &temp
	}
	return nil
}

func assign_listeners(d *schema.ResourceData, target *[]brightbox.LoadBalancerListener) {
	if d.HasChange("listener") {
		*target = expandListeners(d.Get("listener").(*schema.Set).List())
	}
}

func assign_nodes(d *schema.ResourceData, target *[]brightbox.LoadBalancerNode) {
	if d.HasChange("nodes") {
		*target = expandNodes(d.Get("nodes").(*schema.Set).List())
	}
}

func expandListeners(configured []interface{}) []brightbox.LoadBalancerListener {
	listeners := make([]brightbox.LoadBalancerListener, len(configured))

	for i, listen_source := range configured {
		data := listen_source.(map[string]interface{})
		listeners[i].Protocol = data["protocol"].(string)
		listeners[i].In = data["in"].(int)
		listeners[i].Out = data["out"].(int)
		if attr, ok := data["timeout"]; ok {
			listeners[i].Timeout = attr.(int)
		}
	}
	return listeners
}

func expandNodes(configured []interface{}) []brightbox.LoadBalancerNode {
	nodes := make([]brightbox.LoadBalancerNode, len(configured))

	for i, data := range configured {
		nodes[i].Node = data.(string)
	}
	return nodes
}

func output_load_balancer_options(opts *brightbox.LoadBalancerOptions) {
	if opts.Name != nil {
		log.Printf("[DEBUG] Load Balancer Name %v", *opts.Name)
	}
	if opts.Nodes != nil {
		log.Printf("[DEBUG] Load Balancer Nodes %#v", opts.Nodes)
	}
	if opts.Policy != nil {
		log.Printf("[DEBUG] Load Balancer Policy %v", *opts.Policy)
	}
	if opts.BufferSize != nil {
		log.Printf("[DEBUG] Load Balancer BufferSize %v", *opts.BufferSize)
	}
	if opts.Listeners != nil {
		log.Printf("[DEBUG] Load Balancer Listeners %#v", opts.Listeners)
	}
	if opts.Healthcheck != nil {
		log.Printf("[DEBUG] Load Balancer Healthcheck %#v", *opts.Healthcheck)
	}
	if opts.CertificatePem != nil {
		log.Printf("[DEBUG] Load Balancer CertificatePem %v", *opts.CertificatePem)
	}
	if opts.CertificatePrivateKey != nil {
		log.Printf("[DEBUG] Load Balancer CertificatePrivateKey %v", *opts.CertificatePrivateKey)
	}
	if opts.SslV3 != nil {
		log.Printf("[DEBUG] Load Balancer SslV3 %v", *opts.SslV3)
	}
}
<|endoftext|>


<commit_before>package poller

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"time"

	"../db"
	"../models"

	"github.com/kurrik/twittergo"
	"labix.org/v2/mgo/bson"
)

const (
	requestUrl     = "/1.1/statuses/user_timeline.json?%v"
	count      int = 1
	longForm       = "Sun Mar 22 17:20:17 +0000 2015"
)

var (
	dbConnection = os.Getenv("MONGODB")
	query        url.Values
	response     *twittergo.APIResponse
	req          *http.Request
	err          error
	results      *twittergo.Timeline
)

type tweets struct {
	TweetId    string `json:"id_str"`
	User       user   `json:"user"`
	DatePosted string `json:"created_at"`
	Text       string `json:"text"`
}

type user struct {
	Name       string `json:"name"`
	ScreenName string `json:"screen_name"`
}

func start(client *twittergo.Client, account account, interval time.Duration) {
	log.Println("Subscribing to: " + account.User)

	go func() {
		ticker := time.NewTicker(interval)
		for _ = range ticker.C {
			poll(client, account)
		}
	}()
}

func poll(client *twittergo.Client, account account) {
	var session = db.Session
	c := session.DB(dbConnection).C("tweets")

	query = url.Values{}
	query.Set("count", fmt.Sprintf("%v", count))
	query.Set("screen_name", account.User)

	endpoint := fmt.Sprintf(requestUrl, query.Encode())
	if req, err = http.NewRequest("GET", endpoint, nil); err != nil {
		fmt.Printf("Could not parse request: %v\n", err)
	} else {
		if response, err = client.SendRequest(req); err != nil {
			fmt.Printf("Could not send request: %v\n", err)
		} else {
			decoder := json.NewDecoder(response.Body)
			var decocedResponse []tweets
			err = decoder.Decode(&decocedResponse)

			if err != nil {
				log.Println(err)
			}

			var tweetToSave models.TweetModel
			tweetToSave.TweetId = decocedResponse[0].TweetId
			tweetToSave.User.Name = decocedResponse[0].User.Name
			tweetToSave.User.ScreenName = decocedResponse[0].User.ScreenName
			tweetToSave.DatePosted, _ = time.Parse(longForm, decocedResponse[0].DatePosted)
			tweetToSave.Text = decocedResponse[0].Text

			// Upsert the document
			_, err := c.Upsert(bson.M{"tweetId": tweetToSave.TweetId}, bson.M{"$set": tweetToSave})

			if err != nil {
				log.Println(err)
			}
		}
	}
}
<commit_msg>Added defer when res closes.<commit_after>package poller

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"time"

	"../db"
	"../models"

	"github.com/kurrik/twittergo"
	"labix.org/v2/mgo/bson"
)

const (
	requestUrl     = "/1.1/statuses/user_timeline.json?%v"
	count      int = 1
	longForm       = "Sun Mar 22 17:20:17 +0000 2015"
)

var (
	dbConnection = os.Getenv("MONGODB")
	query        url.Values
	response     *twittergo.APIResponse
	req          *http.Request
	err          error
	results      *twittergo.Timeline
)

type tweets struct {
	TweetId    string `json:"id_str"`
	User       user   `json:"user"`
	DatePosted string `json:"created_at"`
	Text       string `json:"text"`
}

type user struct {
	Name       string `json:"name"`
	ScreenName string `json:"screen_name"`
}

func start(client *twittergo.Client, account account, interval time.Duration) {
	log.Println("Subscribing to: " + account.User)

	go func() {
		ticker := time.NewTicker(interval)
		for _ = range ticker.C {
			poll(client, account)
		}
	}()
}

func poll(client *twittergo.Client, account account) {
	var session = db.Session
	c := session.DB(dbConnection).C("tweets")

	query = url.Values{}
	query.Set("count", fmt.Sprintf("%v", count))
	query.Set("screen_name", account.User)

	endpoint := fmt.Sprintf(requestUrl, query.Encode())
	if req, err = http.NewRequest("GET", endpoint, nil); err != nil {
		fmt.Printf("Could not parse request: %v\n", err)
	} else {
		if response, err = client.SendRequest(req); err != nil {
			fmt.Printf("Could not send request: %v\n", err)
		} else {
			decoder := json.NewDecoder(response.Body)
			var decocedResponse []tweets
			err = decoder.Decode(&decocedResponse)

			if err != nil {
				log.Println(err)
			}

			var tweetToSave models.TweetModel
			tweetToSave.TweetId = decocedResponse[0].TweetId
			tweetToSave.User.Name = decocedResponse[0].User.Name
			tweetToSave.User.ScreenName = decocedResponse[0].User.ScreenName
			tweetToSave.DatePosted, _ = time.Parse(longForm, decocedResponse[0].DatePosted)
			tweetToSave.Text = decocedResponse[0].Text

			// Upsert the document
			_, err := c.Upsert(bson.M{"tweetId": tweetToSave.TweetId}, bson.M{"$set": tweetToSave})

			if err != nil {
				log.Println(err)
			}
		}

		defer response.Body.Close()
	}
}
<|endoftext|>


<commit_before>package app_test

import (
	"testing"

	"os"
	"path"

	"os/user"

	"github.com/luistm/banksaurus/app"
	"github.com/luistm/testkit"
)

func TestUnitNewApp(t *testing.T) {

	// Try to create app in existing directory, but invalid project path
	// Try to create app with non existing configuration file

	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	testCase := []struct {
		name                  string
		configurationFilePath string
		expectedApp           *app.App
		expectedErr           string
	}{
		{
			name: "Creates app",
			configurationFilePath: path.Join(pwd, "..", "/configurations/test_conf.json"),
			expectedApp:           &app.App{ProjectPath: path.Join(pwd, "/..")},
		},
		{
			name: "Creates app with non exiting directory",
			configurationFilePath: "/ThisDirectoryDoesNotExist",
			expectedApp:           &app.App{},
			expectedErr:           app.ErrPathDoesNotExist.Error(),
		},
		{
			name: "Creates app with non exiting configuration file",
			configurationFilePath: path.Join(pwd, "..", "/configurations/t_conf.json"),
			expectedApp:           &app.App{},
			expectedErr:           app.ErrPathDoesNotExist.Error(),
		},
		{
			name: "Creates app in invalid project structure",
			configurationFilePath: "/tmp",
			expectedApp:           &app.App{},
			expectedErr:           app.ErrInvalidAppStructure.Error(),
		},
	}

	for _, tc := range testCase {
		t.Run(tc.name, func(t *testing.T) {
			application, err := app.New(tc.configurationFilePath)

			if tc.expectedErr != "" {
				testkit.AssertEqual(t, tc.expectedErr, err.Error())
			}
			testkit.AssertEqual(t, tc.expectedApp, application)
		})
	}
}

func TestUnitValidatePath(t *testing.T) {

	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	testCases := []struct {
		name   string
		input  string
		errMsg string
	}{
		{
			name:   "Returns error if path does not exist",
			input:  path.Join(pwd, "..", "/ThisPathDoesNotExist"),
			errMsg: app.ErrPathDoesNotExist.Error(),
		},
		//{
		//	name:   "Returns error if path is file",
		//	input:  path.Join(pwd, "..", "/app/app.go"),
		//	errMsg: app.ErrPathIsFile.Error(),
		//},
		{
			name:   "Returns error if path does not have prefix '/'",
			input:  "app/app.go",
			errMsg: app.ErrMalformedPath.Error(),
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			err := app.ValidatePath(tc.input)

			// Error is expected
			if tc.errMsg != "" {
				testkit.AssertEqual(t, tc.errMsg, err.Error())
			}
		})
	}
}

func TestUnitGetDataBasePath(t *testing.T) {

	usr, err := user.Current()
	if err != nil {
		t.Fatal(err)
	}
	expectedDbName := "services"
	expectedDbPath := path.Join(usr.HomeDir, ".services")

	dbName, dbPath := app.DatabasePath()

	testkit.AssertEqual(t, expectedDbName, dbName)
	testkit.AssertEqual(t, expectedDbPath, dbPath)

	os.Setenv("BANKSAURUS_ENV", "true")
	defer os.Setenv("BANKSAURUS_ENV", "")

	expectedDbName = "services"
	expectedDbPath = os.TempDir()

	dbName, dbPath = app.DatabasePath()

	testkit.AssertEqual(t, expectedDbName, dbName)
	testkit.AssertEqual(t, expectedDbPath, dbPath)
}
<commit_msg>Fix for bad environment variable value<commit_after>package app_test

import (
	"testing"

	"os"
	"path"

	"os/user"

	"github.com/luistm/banksaurus/app"
	"github.com/luistm/testkit"
)

func TestUnitNewApp(t *testing.T) {

	// Try to create app in existing directory, but invalid project path
	// Try to create app with non existing configuration file

	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	testCase := []struct {
		name                  string
		configurationFilePath string
		expectedApp           *app.App
		expectedErr           string
	}{
		{
			name: "Creates app",
			configurationFilePath: path.Join(pwd, "..", "/configurations/test_conf.json"),
			expectedApp:           &app.App{ProjectPath: path.Join(pwd, "/..")},
		},
		{
			name: "Creates app with non exiting directory",
			configurationFilePath: "/ThisDirectoryDoesNotExist",
			expectedApp:           &app.App{},
			expectedErr:           app.ErrPathDoesNotExist.Error(),
		},
		{
			name: "Creates app with non exiting configuration file",
			configurationFilePath: path.Join(pwd, "..", "/configurations/t_conf.json"),
			expectedApp:           &app.App{},
			expectedErr:           app.ErrPathDoesNotExist.Error(),
		},
		{
			name: "Creates app in invalid project structure",
			configurationFilePath: "/tmp",
			expectedApp:           &app.App{},
			expectedErr:           app.ErrInvalidAppStructure.Error(),
		},
	}

	for _, tc := range testCase {
		t.Run(tc.name, func(t *testing.T) {
			application, err := app.New(tc.configurationFilePath)

			if tc.expectedErr != "" {
				testkit.AssertEqual(t, tc.expectedErr, err.Error())
			}
			testkit.AssertEqual(t, tc.expectedApp, application)
		})
	}
}

func TestUnitValidatePath(t *testing.T) {

	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	testCases := []struct {
		name   string
		input  string
		errMsg string
	}{
		{
			name:   "Returns error if path does not exist",
			input:  path.Join(pwd, "..", "/ThisPathDoesNotExist"),
			errMsg: app.ErrPathDoesNotExist.Error(),
		},
		//{
		//	name:   "Returns error if path is file",
		//	input:  path.Join(pwd, "..", "/app/app.go"),
		//	errMsg: app.ErrPathIsFile.Error(),
		//},
		{
			name:   "Returns error if path does not have prefix '/'",
			input:  "app/app.go",
			errMsg: app.ErrMalformedPath.Error(),
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			err := app.ValidatePath(tc.input)

			// Error is expected
			if tc.errMsg != "" {
				testkit.AssertEqual(t, tc.errMsg, err.Error())
			}
		})
	}
}

func TestUnitGetDataBasePath(t *testing.T) {

	usr, err := user.Current()
	if err != nil {
		t.Fatal(err)
	}
	expectedDbName := "services"
	expectedDbPath := path.Join(usr.HomeDir, ".services")

	dbName, dbPath := app.DatabasePath()

	testkit.AssertEqual(t, expectedDbName, dbName)
	testkit.AssertEqual(t, expectedDbPath, dbPath)

	os.Setenv("BANKSAURUS_ENV", "dev")
	defer os.Setenv("BANKSAURUS_ENV", "")

	expectedDbName = "services"
	expectedDbPath = os.TempDir()

	dbName, dbPath = app.DatabasePath()

	testkit.AssertEqual(t, expectedDbName, dbName)
	testkit.AssertEqual(t, expectedDbPath, dbPath)
}
<|endoftext|>


<commit_before>package portping

import (
	"testing"
	"net"
	"strings"
	"time"
	"strconv"
)

const (
	testHost = "localhost"
	knownNonexistentHost = "nonexistent.janosgyerik.com"
	defaultTimeout = 5 * time.Second
	testNetwork = "tcp"
)

var testPort = findKnownAvailablePort()

func findKnownAvailablePort() string {
	tcpa, err := net.ResolveTCPAddr("tcp", ":0")
	if err != nil {
		panic(err)
	}
	ln, err := net.ListenTCP("tcp", tcpa)
	if err != nil {
		panic(err)
	}
	defer ln.Close()

	local, ok := ln.Addr().(*net.TCPAddr)
	if !ok {
		panic("Unable to convert Addr to TCPAddr")
	}

	return strconv.Itoa(local.Port)
}

func acceptN(t*testing.T, host, port string, count int) {
	ready := make(chan bool)
	go func() {
		ln, err := net.Listen(testNetwork, net.JoinHostPort(host, port))
		if err != nil {
			t.Fatal(err)
		}
		defer ln.Close()

		ready <- true

		for i := 0; i < count; i++ {
			conn, err := ln.Accept()
			if err != nil {
				t.Fatal(err)
			}
			conn.Close()
		}
	}()
	<-ready
}

func assertPingResult(t*testing.T, host, port string, expectSuccess bool, patterns ...string) {
	addr := net.JoinHostPort(host, port)
	err := Ping(testNetwork, addr, defaultTimeout)
	t.Logf("port ping %s -> %v", addr, err)

	if err != nil {
		if expectSuccess {
			t.Errorf("ping to %s failed; expected success", addr)
		} else {
			assertErrorContains(t, err, patterns...)
		}
	} else {
		if !expectSuccess {
			t.Errorf("ping to %s success; expected failure", addr)
		}
	}
}

func assertErrorContains(t*testing.T, err error, patterns ...string) {
	result := err.Error()
	foundMatch := false
	for _, pattern := range patterns {
		if strings.Contains(result, pattern) {
			foundMatch = true
			break
		}
	}
	if !foundMatch {
		t.Errorf("got '%s'; expected to contain one of '%s'", result, patterns)
	}
}

func assertPingFailure(t*testing.T, host, port string, patterns ...string) {
	assertPingResult(t, host, port, false, patterns...)
}

func assertPingNSuccessCount(t*testing.T, host, port string, pingCount int, expectedSuccessCount int) {
	c := make(chan error)
	addr := net.JoinHostPort(host, port)
	go PingN(testNetwork, addr, defaultTimeout, pingCount, c)

	failureCount := 0
	for i := 0; i < pingCount; i++ {
		err := <-c
		t.Logf("port ping %s [%d] -> %v", addr, i + 1, err)

		if err != nil {
			failureCount++
		}
	}

	successCount := pingCount - failureCount
	if expectedSuccessCount != successCount {
		t.Errorf("expected %d successful pings, but got only %d", expectedSuccessCount, successCount)
	}
}

func Test_ping_open_port(t*testing.T) {
	acceptN(t, testHost, testPort, 1)

	assertPingResult(t, testHost, testPort, true)

	// for sanity: acceptN should have shut down already
	assertPingFailure(t, testHost, testPort, "connection refused")
}

func Test_ping_unopen_port(t*testing.T) {
	assertPingFailure(t, testHost, testPort, "connection refused")
}

func Test_ping_nonexistent_host(t*testing.T) {
	assertPingFailure(t, knownNonexistentHost, testPort, "no such host")
}

func Test_ping_negative_port(t*testing.T) {
	assertPingFailure(t, testHost, "-1", "invalid port", "unknown port")
}

func Test_ping_too_high_port(t*testing.T) {
	assertPingFailure(t, testHost, "123456", "invalid port", "unknown port")
}

func Test_ping5_all_success(t*testing.T) {
	pingCount := 3
	acceptN(t, testHost, testPort, pingCount)

	assertPingNSuccessCount(t, testHost, testPort, pingCount, pingCount)
}

func Test_ping5_all_fail(t*testing.T) {
	pingCount := 5
	successCount := 0
	assertPingNSuccessCount(t, testHost, testPort, pingCount, successCount)
}

func Test_ping5_partial_success(t*testing.T) {
	successCount := 3
	acceptN(t, testHost, testPort, successCount)

	pingCount := 5
	assertPingNSuccessCount(t, testHost, testPort, pingCount, successCount)
}
<commit_msg>flipped test condition order to actual, expected<commit_after>package portping

import (
	"testing"
	"net"
	"strings"
	"time"
	"strconv"
)

const (
	testHost = "localhost"
	knownNonexistentHost = "nonexistent.janosgyerik.com"
	defaultTimeout = 5 * time.Second
	testNetwork = "tcp"
)

var testPort = findKnownAvailablePort()

func findKnownAvailablePort() string {
	tcpa, err := net.ResolveTCPAddr("tcp", ":0")
	if err != nil {
		panic(err)
	}
	ln, err := net.ListenTCP("tcp", tcpa)
	if err != nil {
		panic(err)
	}
	defer ln.Close()

	local, ok := ln.Addr().(*net.TCPAddr)
	if !ok {
		panic("Unable to convert Addr to TCPAddr")
	}

	return strconv.Itoa(local.Port)
}

func acceptN(t*testing.T, host, port string, count int) {
	ready := make(chan bool)
	go func() {
		ln, err := net.Listen(testNetwork, net.JoinHostPort(host, port))
		if err != nil {
			t.Fatal(err)
		}
		defer ln.Close()

		ready <- true

		for i := 0; i < count; i++ {
			conn, err := ln.Accept()
			if err != nil {
				t.Fatal(err)
			}
			conn.Close()
		}
	}()
	<-ready
}

func assertPingResult(t*testing.T, host, port string, expectSuccess bool, patterns ...string) {
	addr := net.JoinHostPort(host, port)
	err := Ping(testNetwork, addr, defaultTimeout)
	t.Logf("port ping %s -> %v", addr, err)

	if err != nil {
		if expectSuccess {
			t.Errorf("ping to %s failed; expected success", addr)
		} else {
			assertErrorContains(t, err, patterns...)
		}
	} else {
		if !expectSuccess {
			t.Errorf("ping to %s success; expected failure", addr)
		}
	}
}

func assertErrorContains(t*testing.T, err error, patterns ...string) {
	result := err.Error()
	foundMatch := false
	for _, pattern := range patterns {
		if strings.Contains(result, pattern) {
			foundMatch = true
			break
		}
	}
	if !foundMatch {
		t.Errorf("got '%s'; expected to contain one of '%s'", result, patterns)
	}
}

func assertPingFailure(t*testing.T, host, port string, patterns ...string) {
	assertPingResult(t, host, port, false, patterns...)
}

func assertPingNSuccessCount(t*testing.T, host, port string, pingCount int, expectedSuccessCount int) {
	c := make(chan error)
	addr := net.JoinHostPort(host, port)
	go PingN(testNetwork, addr, defaultTimeout, pingCount, c)

	failureCount := 0
	for i := 0; i < pingCount; i++ {
		err := <-c
		t.Logf("port ping %s [%d] -> %v", addr, i + 1, err)

		if err != nil {
			failureCount++
		}
	}

	successCount := pingCount - failureCount
	if successCount != expectedSuccessCount {
		t.Errorf("expected %d successful pings, but got %d", expectedSuccessCount, successCount)
	}
}

func Test_ping_open_port(t*testing.T) {
	acceptN(t, testHost, testPort, 1)

	assertPingResult(t, testHost, testPort, true)

	// for sanity: acceptN should have shut down already
	assertPingFailure(t, testHost, testPort, "connection refused")
}

func Test_ping_unopen_port(t*testing.T) {
	assertPingFailure(t, testHost, testPort, "connection refused")
}

func Test_ping_nonexistent_host(t*testing.T) {
	assertPingFailure(t, knownNonexistentHost, testPort, "no such host")
}

func Test_ping_negative_port(t*testing.T) {
	assertPingFailure(t, testHost, "-1", "invalid port", "unknown port")
}

func Test_ping_too_high_port(t*testing.T) {
	assertPingFailure(t, testHost, "123456", "invalid port", "unknown port")
}

func Test_ping5_all_success(t*testing.T) {
	pingCount := 3
	acceptN(t, testHost, testPort, pingCount)

	assertPingNSuccessCount(t, testHost, testPort, pingCount, pingCount)
}

func Test_ping5_all_fail(t*testing.T) {
	pingCount := 5
	successCount := 0
	assertPingNSuccessCount(t, testHost, testPort, pingCount, successCount)
}

func Test_ping5_partial_success(t*testing.T) {
	successCount := 3
	acceptN(t, testHost, testPort, successCount)

	pingCount := 5
	assertPingNSuccessCount(t, testHost, testPort, pingCount, successCount)
}
<|endoftext|>


<commit_before>package log

import (
	"bytes"
	"encoding/json"
	"errors"
	"reflect"
	"strconv"
	"time"
)

// JSONFormatter formats log entries as JSON. This should be used
// in production because it is machine parseable.
type JSONFormatter struct {
	name string
}

// NewJSONFormatter creates a new instance of JSONFormatter.
func NewJSONFormatter(name string) *JSONFormatter {
	return &JSONFormatter{name: name}
}

var errorType = reflect.TypeOf(errors.New(""))

func (jf *JSONFormatter) appendValue(buf *bytes.Buffer, val interface{}) {
	if val == nil {
		buf.WriteString("null")
		return
	}

	value := reflect.ValueOf(val)
	kind := value.Kind()
	if kind == reflect.Ptr {
		value = value.Elem()
		kind = value.Kind()
	}
	switch kind {
	case reflect.Bool:
		if value.Bool() {
			buf.WriteString("true")
		} else {
			buf.WriteString("false")
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		buf.WriteString(strconv.FormatInt(value.Int(), 10))

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		buf.WriteString(strconv.FormatUint(value.Uint(), 10))

	case reflect.Float32:
		buf.WriteString(strconv.FormatFloat(value.Float(), 'g', -1, 32))

	case reflect.Float64:
		buf.WriteString(strconv.FormatFloat(value.Float(), 'g', -1, 64))

	default:
		if err, ok := val.(error); ok {
			buf.WriteString(strconv.Quote(err.Error()))
			return
		}

		b, err := json.Marshal(value.Interface())
		if err != nil {
			buf.WriteString("Could not json.Marshal value: ")
			buf.WriteString(err.Error())
		}
		buf.Write(b)
	}
}

func (jf *JSONFormatter) set(buf *bytes.Buffer, key string, val interface{}) {
	// WARNING: assumes this is not first key
	buf.WriteString(`, "`)
	buf.WriteString(key)
	buf.WriteString(`":`)
	jf.appendValue(buf, val)
}

// Format formats log entry as JSON.
func (jf *JSONFormatter) Format(buf *bytes.Buffer, level int, msg string, args []interface{}) {
	buf.WriteString(`{"t":"`)
	buf.WriteString(time.Now().Format(timeFormat))
	buf.WriteRune('"')

	buf.WriteString(`, "l":"`)
	buf.WriteString(LevelMap[level])
	buf.WriteRune('"')

	buf.WriteString(`, "n":"`)
	buf.WriteString(jf.name)
	buf.WriteRune('"')

	buf.WriteString(`, "m":`)
	jf.appendValue(buf, msg)

	var lenArgs = len(args)
	if lenArgs > 0 {
		if lenArgs%2 == 0 {
			for i := 0; i < lenArgs; i += 2 {
				if key, ok := args[i].(string); ok {
					if key == "" {
						// key is invalid. Let the user know and adjust
						// for the first argument being the message
						jf.set(buf, "BADKEY"+strconv.Itoa(i+1), args[i+1])
					} else {
						jf.set(buf, key, args[i+1])
					}
				} else {
					// key is invalid. Let the user know and adjust
					// for the first argument being the message
					jf.set(buf, "BADKEY"+strconv.Itoa(i+1), args[i+1])
				}
			}
		} else {
			jf.set(buf, warnImbalancedKey, args)
		}
	}
	buf.WriteString("}\n")
}

// LogEntry returns the JSON log entry object built by Format().
func (jf *JSONFormatter) LogEntry(level int, msg string, args []interface{}) map[string]interface{} {
	var buf bytes.Buffer
	jf.Format(&buf, level, msg, args)
	var entry map[string]interface{}
	err := json.Unmarshal(buf.Bytes(), &entry)
	if err != nil {
		panic("Unable to unmarhsal entry from JSONFormatter: " + err.Error())
	}
	return entry
}

// SetName sets the name of this formatter.
func (jf *JSONFormatter) SetName(name string) {
	jf.name = name
}
<commit_msg>default to sprintf when JSON cannot be marshalled<commit_after>package log

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"time"
)

// JSONFormatter formats log entries as JSON. This should be used
// in production because it is machine parseable.
type JSONFormatter struct {
	name string
}

// NewJSONFormatter creates a new instance of JSONFormatter.
func NewJSONFormatter(name string) *JSONFormatter {
	return &JSONFormatter{name: name}
}

var errorType = reflect.TypeOf(errors.New(""))

func (jf *JSONFormatter) appendValue(buf *bytes.Buffer, val interface{}) {
	if val == nil {
		buf.WriteString("null")
		return
	}

	value := reflect.ValueOf(val)
	kind := value.Kind()
	if kind == reflect.Ptr {
		value = value.Elem()
		kind = value.Kind()
	}
	switch kind {
	case reflect.Bool:
		if value.Bool() {
			buf.WriteString("true")
		} else {
			buf.WriteString("false")
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		buf.WriteString(strconv.FormatInt(value.Int(), 10))

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		buf.WriteString(strconv.FormatUint(value.Uint(), 10))

	case reflect.Float32:
		buf.WriteString(strconv.FormatFloat(value.Float(), 'g', -1, 32))

	case reflect.Float64:
		buf.WriteString(strconv.FormatFloat(value.Float(), 'g', -1, 64))

	// case reflect.String:
	// 	buf.WriteString(strconv.Quote(value.String()))

	default:
		if err, ok := val.(error); ok {
			buf.WriteString(strconv.Quote(err.Error()))
			return
		}

		b, err := json.Marshal(value.Interface())
		if err != nil {
			internalLog.Error("Could not json.Marshal value: ", "formatter", "JSONFormatter", "err", err.Error())
			// must always log, use sprintf to get a string
			s := fmt.Sprintf("%v", value.Interface())
			b, _ := json.Marshal(s)
			buf.Write(b)
		}
		buf.Write(b)
	}
}

func (jf *JSONFormatter) set(buf *bytes.Buffer, key string, val interface{}) {
	// WARNING: assumes this is not first key
	buf.WriteString(`, "`)
	buf.WriteString(key)
	buf.WriteString(`":`)
	jf.appendValue(buf, val)
}

// Format formats log entry as JSON.
func (jf *JSONFormatter) Format(buf *bytes.Buffer, level int, msg string, args []interface{}) {
	buf.WriteString(`{"t":"`)
	buf.WriteString(time.Now().Format(timeFormat))
	buf.WriteRune('"')

	buf.WriteString(`, "l":"`)
	buf.WriteString(LevelMap[level])
	buf.WriteRune('"')

	buf.WriteString(`, "n":"`)
	buf.WriteString(jf.name)
	buf.WriteRune('"')

	buf.WriteString(`, "m":`)
	jf.appendValue(buf, msg)

	var lenArgs = len(args)
	if lenArgs > 0 {
		if lenArgs%2 == 0 {
			for i := 0; i < lenArgs; i += 2 {
				if key, ok := args[i].(string); ok {
					if key == "" {
						// key is invalid. Let the user know and adjust
						// for the first argument being the message
						jf.set(buf, "BADKEY"+strconv.Itoa(i+1), args[i+1])
					} else {
						jf.set(buf, key, args[i+1])
					}
				} else {
					// key is invalid. Let the user know and adjust
					// for the first argument being the message
					jf.set(buf, "BADKEY"+strconv.Itoa(i+1), args[i+1])
				}
			}
		} else {
			jf.set(buf, warnImbalancedKey, args)
		}
	}
	buf.WriteString("}\n")
}

// LogEntry returns the JSON log entry object built by Format().
func (jf *JSONFormatter) LogEntry(level int, msg string, args []interface{}) map[string]interface{} {
	var buf bytes.Buffer
	jf.Format(&buf, level, msg, args)
	var entry map[string]interface{}
	err := json.Unmarshal(buf.Bytes(), &entry)
	if err != nil {
		panic("Unable to unmarhsal entry from JSONFormatter: " + err.Error())
	}
	return entry
}

// SetName sets the name of this formatter.
func (jf *JSONFormatter) SetName(name string) {
	jf.name = name
}
<|endoftext|>


<commit_before>// Copyright 2013 Matthew Baird
// 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 elastigo

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

// Get allows caller to get a typed JSON document from the index based on its id.
// GET - retrieves the doc
// HEAD - checks for existence of the doc
// http://www.elasticsearch.org/guide/reference/api/get.html
// TODO: make this implement an interface
func (c *Conn) get(index string, _type string, id string, args map[string]interface{}, source *json.RawMessage) (BaseResponse, error) {
	var url string
	retval := BaseResponse{Source: source}
	if len(_type) > 0 {
		url = fmt.Sprintf("/%s/%s/%s", index, _type, id)
	} else {
		url = fmt.Sprintf("/%s/%s", index, id)
	}
	body, err := c.DoCommand("GET", url, args, nil)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal(body, &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	return retval, err
}

// The get API allows to get a typed JSON document from the index based on its id.
// GET - retrieves the doc
// HEAD - checks for existence of the doc
// http://www.elasticsearch.org/guide/reference/api/get.html
// TODO: make this implement an interface
func (c *Conn) Get(index string, _type string, id string, args map[string]interface{}) (BaseResponse, error) {
	return c.get(index, _type, id, args, nil)
}

// Same as Get but with custom source type.
func (c *Conn) GetCustom(index string, _type string, id string, args map[string]interface{}, source *json.RawMessage) (BaseResponse, error) {
	return c.get(index, _type, id, args, source)
}

// GetSource retrieves the document by id and converts it to provided interface
func (c *Conn) GetSource(index string, _type string, id string, args map[string]interface{}, source interface{}) error {
	url := fmt.Sprintf("/%s/%s/%s/_source", index, _type, id)
	body, err := c.DoCommand("GET", url, args, nil)
	if err == nil {
		err = json.Unmarshal(body, &source)
	}
	return err
}

// ExistsBool allows caller to check for the existence of a document using HEAD
// TODO(shutej): This looks redundant with the Exists function in
// baserequest.go, check with mattbaird@.
func (c *Conn) ExistsBool(index string, _type string, id string, args map[string]interface{}) (bool, error) {

	var url string

	query, err := Escape(args)
	if err != nil {
		return false, err
	}

	if len(_type) > 0 {
		url = fmt.Sprintf("/%s/%s/%s", index, _type, id)
	} else {
		url = fmt.Sprintf("/%s/%s", index, id)
	}

	req, err := c.NewRequest("HEAD", url, query)
	if err != nil {
		return false, err
	}

	httpStatusCode, _, err := req.Do(nil)

	// RecordNotFound is the expected response for a non-existent document,
	// so we don't return an error to our caller
	if err == RecordNotFound {
		return false, nil
	}

	return httpStatusCode == http.StatusOK, err
}

// ExistsIndex allows caller to check for the existance of an index or a type using HEAD
func (c *Conn) ExistsIndex(index string, _type string, args map[string]interface{}) (bool, error) {
	var url string

	query, err := Escape(args)
	if err != nil {
		return false, err
	}

	if len(_type) > 0 {
		url = fmt.Sprintf("/%s/%s", index, _type)
	} else {
		url = fmt.Sprintf("/%s", index)
	}
	req, err := c.NewRequest("HEAD", url, query)
	httpStatusCode, _, err := req.Do(nil)

	if err != nil {
		return false, err
	}
	if httpStatusCode == http.StatusOK {
		return true, err
	}
	return false, err
}
<commit_msg>fix typo<commit_after>// Copyright 2013 Matthew Baird
// 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 elastigo

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

// Get allows caller to get a typed JSON document from the index based on its id.
// GET - retrieves the doc
// HEAD - checks for existence of the doc
// http://www.elasticsearch.org/guide/reference/api/get.html
// TODO: make this implement an interface
func (c *Conn) get(index string, _type string, id string, args map[string]interface{}, source *json.RawMessage) (BaseResponse, error) {
	var url string
	retval := BaseResponse{Source: source}
	if len(_type) > 0 {
		url = fmt.Sprintf("/%s/%s/%s", index, _type, id)
	} else {
		url = fmt.Sprintf("/%s/%s", index, id)
	}
	body, err := c.DoCommand("GET", url, args, nil)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal(body, &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	return retval, err
}

// The get API allows to get a typed JSON document from the index based on its id.
// GET - retrieves the doc
// HEAD - checks for existence of the doc
// http://www.elasticsearch.org/guide/reference/api/get.html
// TODO: make this implement an interface
func (c *Conn) Get(index string, _type string, id string, args map[string]interface{}) (BaseResponse, error) {
	return c.get(index, _type, id, args, nil)
}

// Same as Get but with custom source type.
func (c *Conn) GetCustom(index string, _type string, id string, args map[string]interface{}, source *json.RawMessage) (BaseResponse, error) {
	return c.get(index, _type, id, args, source)
}

// GetSource retrieves the document by id and converts it to provided interface
func (c *Conn) GetSource(index string, _type string, id string, args map[string]interface{}, source interface{}) error {
	url := fmt.Sprintf("/%s/%s/%s/_source", index, _type, id)
	body, err := c.DoCommand("GET", url, args, nil)
	if err == nil {
		err = json.Unmarshal(body, &source)
	}
	return err
}

// ExistsBool allows caller to check for the existence of a document using HEAD
// TODO(shutej): This looks redundant with the Exists function in
// baserequest.go, check with mattbaird@.
func (c *Conn) ExistsBool(index string, _type string, id string, args map[string]interface{}) (bool, error) {

	var url string

	query, err := Escape(args)
	if err != nil {
		return false, err
	}

	if len(_type) > 0 {
		url = fmt.Sprintf("/%s/%s/%s", index, _type, id)
	} else {
		url = fmt.Sprintf("/%s/%s", index, id)
	}

	req, err := c.NewRequest("HEAD", url, query)
	if err != nil {
		return false, err
	}

	httpStatusCode, _, err := req.Do(nil)

	// RecordNotFound is the expected response for a non-existent document,
	// so we don't return an error to our caller
	if err == RecordNotFound {
		return false, nil
	}

	return httpStatusCode == http.StatusOK, err
}

// ExistsIndex allows caller to check for the existence of an index or a type using HEAD
func (c *Conn) ExistsIndex(index string, _type string, args map[string]interface{}) (bool, error) {
	var url string

	query, err := Escape(args)
	if err != nil {
		return false, err
	}

	if len(_type) > 0 {
		url = fmt.Sprintf("/%s/%s", index, _type)
	} else {
		url = fmt.Sprintf("/%s", index)
	}
	req, err := c.NewRequest("HEAD", url, query)
	httpStatusCode, _, err := req.Do(nil)

	if err != nil {
		return false, err
	}
	if httpStatusCode == http.StatusOK {
		return true, err
	}
	return false, err
}
<|endoftext|>


<commit_before>// Copyright 2015 Auburn University. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package names

import (
	"go/token"
	"go/types"
)

// FindConflict determines if there already exists an identifier with the given
// newName such that the given ident cannot be renamed to name.  It returns
// one such conflicting declaration, if possible, and nil if there are none.
func FindConflict(obj types.Object, name string) types.Object {
	// XXX: The checks here are unnecessarily conservative.  This looks for
	// any declaration with the same name in any related scope; it does not
	// consider *references*, which really determine whether a conflict
	// exists.

	if obj == nil { // Probably package or switch variable
		return nil
	}

	// Check for conflicts in the current scope or any child scope
	if obj.Parent() != nil {
		if result := findConflictInChildScope(obj.Parent(), name); result != nil {
			return result
		}
	}

	// Check for conflicting methods on the receiver type, if applicable
	if isMethod(obj) {
		objfound, _, pointerindirections := types.LookupFieldOrMethod(
			methodReceiver(obj).Type(), true, obj.Pkg(), name)
		if isMethod(objfound) && pointerindirections {
			return objfound
		}
	}

	// Check for possible conflicts from a parent scope
	if _, obj := obj.Parent().LookupParent(name, token.NoPos); obj != nil {
		return obj
	}

	return nil
}

func findConflictInChildScope(scope *types.Scope, name string) types.Object {
	if obj := scope.Lookup(name); obj != nil {
		return obj
	}

	for i := 0; i < scope.NumChildren(); i++ {
		if obj := findConflictInChildScope(scope.Child(i), name); obj != nil {
			return obj
		}
	}
	return nil
}
<commit_msg>Add package doc for analysis/names<commit_after>// Copyright 2015 Auburn University. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package names provides functions to analyze the usage names (functions,
// types, variables, etc.) across multiple files.
package names

import (
	"go/token"
	"go/types"
)

// FindConflict determines if there already exists an identifier with the given
// newName such that the given ident cannot be renamed to name.  It returns
// one such conflicting declaration, if possible, and nil if there are none.
func FindConflict(obj types.Object, name string) types.Object {
	// XXX: The checks here are unnecessarily conservative.  This looks for
	// any declaration with the same name in any related scope; it does not
	// consider *references*, which really determine whether a conflict
	// exists.

	if obj == nil { // Probably package or switch variable
		return nil
	}

	// Check for conflicts in the current scope or any child scope
	if obj.Parent() != nil {
		if result := findConflictInChildScope(obj.Parent(), name); result != nil {
			return result
		}
	}

	// Check for conflicting methods on the receiver type, if applicable
	if isMethod(obj) {
		objfound, _, pointerindirections := types.LookupFieldOrMethod(
			methodReceiver(obj).Type(), true, obj.Pkg(), name)
		if isMethod(objfound) && pointerindirections {
			return objfound
		}
	}

	// Check for possible conflicts from a parent scope
	if _, obj := obj.Parent().LookupParent(name, token.NoPos); obj != nil {
		return obj
	}

	return nil
}

func findConflictInChildScope(scope *types.Scope, name string) types.Object {
	if obj := scope.Lookup(name); obj != nil {
		return obj
	}

	for i := 0; i < scope.NumChildren(); i++ {
		if obj := findConflictInChildScope(scope.Child(i), name); obj != nil {
			return obj
		}
	}
	return nil
}
<|endoftext|>