<commit_before>// Copyright (c) 2017 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package gnmi

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"path"
	"strconv"

	pb "github.com/openconfig/gnmi/proto/gnmi"
	"google.golang.org/grpc/codes"
)

// Get sents a GetRequest to the given client.
func Get(ctx context.Context, client pb.GNMIClient, paths [][]string) error {
	req, err := NewGetRequest(paths)
	if err != nil {
		return err
	}
	resp, err := client.Get(ctx, req)
	if err != nil {
		return err
	}
	for _, notif := range resp.Notification {
		for _, update := range notif.Update {
			fmt.Printf("%s:\n", StrPath(update.Path))
			fmt.Println(StrUpdateVal(update))
		}
	}
	return nil
}

// Capabilities retuns the capabilities of the client.
func Capabilities(ctx context.Context, client pb.GNMIClient) error {
	resp, err := client.Capabilities(ctx, &pb.CapabilityRequest{})
	if err != nil {
		return err
	}
	fmt.Printf("Version: %s\n", resp.GNMIVersion)
	for _, mod := range resp.SupportedModels {
		fmt.Printf("SupportedModel: %s\n", mod)
	}
	for _, enc := range resp.SupportedEncodings {
		fmt.Printf("SupportedEncoding: %s\n", enc)
	}
	return nil
}

// val may be a path to a file or it may be json. First see if it is a
// file, if so return its contents, otherwise return val
func extractJSON(val string) []byte {
	jsonBytes, err := ioutil.ReadFile(val)
	if err != nil {
		jsonBytes = []byte(val)
	}
	return jsonBytes
}

// StrUpdateVal will return a string representing the value within the supplied update
func StrUpdateVal(u *pb.Update) string {
	if u.Value != nil {
		// Backwards compatibility with pre-v0.4 gnmi
		switch u.Value.Type {
		case pb.Encoding_JSON, pb.Encoding_JSON_IETF:
			return strJSON(u.Value.Value)
		case pb.Encoding_BYTES, pb.Encoding_PROTO:
			base64.StdEncoding.EncodeToString(u.Value.Value)
		case pb.Encoding_ASCII:
			return string(u.Value.Value)
		default:
			return string(u.Value.Value)
		}
	}
	return strVal(u.Val)
}

// strVal will return a string representing the supplied value
func strVal(val *pb.TypedValue) string {
	switch v := val.GetValue().(type) {
	case *pb.TypedValue_StringVal:
		return v.StringVal
	case *pb.TypedValue_JsonIetfVal:
		return strJSON(v.JsonIetfVal)
	case *pb.TypedValue_JsonVal:
		return strJSON(v.JsonVal)
	case *pb.TypedValue_IntVal:
		return strconv.FormatInt(v.IntVal, 10)
	case *pb.TypedValue_UintVal:
		return strconv.FormatUint(v.UintVal, 10)
	case *pb.TypedValue_BoolVal:
		return strconv.FormatBool(v.BoolVal)
	case *pb.TypedValue_BytesVal:
		return base64.StdEncoding.EncodeToString(v.BytesVal)
	case *pb.TypedValue_DecimalVal:
		return strDecimal64(v.DecimalVal)
	case *pb.TypedValue_FloatVal:
		return strconv.FormatFloat(float64(v.FloatVal), 'g', -1, 32)
	case *pb.TypedValue_LeaflistVal:
		return strLeaflist(v.LeaflistVal)
	case *pb.TypedValue_AsciiVal:
		return v.AsciiVal
	case *pb.TypedValue_AnyVal:
		return v.AnyVal.String()
	default:
		panic(v)
	}
}

func strJSON(inJSON []byte) string {
	var out bytes.Buffer
	err := json.Indent(&out, inJSON, "", "  ")
	if err != nil {
		return fmt.Sprintf("(error unmarshalling json: %s)\n", err) + string(inJSON)
	}
	return out.String()
}

func strDecimal64(d *pb.Decimal64) string {
	var i, frac uint64
	if d.Precision > 0 {
		div := uint64(10)
		it := d.Precision - 1
		for it > 0 {
			div *= 10
			it--
		}
		i = d.Digits / div
		frac = d.Digits % div
	} else {
		i = d.Digits
	}
	return fmt.Sprintf("%d.%d", i, frac)
}

// strLeafList builds a human-readable form of a leaf-list. e.g. [1,2,3] or [a,b,c]
func strLeaflist(v *pb.ScalarArray) string {
	s := make([]string, 0, len(v.Element))
	sz := 2 // []

	// convert arbitrary TypedValues to string form
	for _, elm := range v.Element {
		str := strVal(elm)
		s = append(s, str)
		sz += len(str) + 1 // %v + ,
	}

	b := make([]byte, sz)
	buf := bytes.NewBuffer(b)

	buf.WriteRune('[')
	for i := range v.Element {
		buf.WriteString(s[i])
		if i < len(v.Element)-1 {
			buf.WriteRune(',')
		}
	}
	buf.WriteRune(']')
	return buf.String()
}

func update(p *pb.Path, val string) *pb.Update {
	var v *pb.TypedValue
	switch p.Origin {
	case "":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_JsonIetfVal{JsonIetfVal: extractJSON(val)}}
	case "cli":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_AsciiVal{AsciiVal: val}}
	default:
		panic(fmt.Errorf("unexpected origin: %q", p.Origin))
	}

	return &pb.Update{Path: p, Val: v}
}

// Operation describes an gNMI operation.
type Operation struct {
	Type string
	Path []string
	Val  string
}

func newSetRequest(setOps []*Operation) (*pb.SetRequest, error) {
	req := &pb.SetRequest{}
	for _, op := range setOps {
		p, err := ParseGNMIElements(op.Path)
		if err != nil {
			return nil, err
		}

		switch op.Type {
		case "delete":
			req.Delete = append(req.Delete, p)
		case "update":
			req.Update = append(req.Update, update(p, op.Val))
		case "replace":
			req.Replace = append(req.Replace, update(p, op.Val))
		}
	}
	return req, nil
}

// Set sends a SetRequest to the given client.
func Set(ctx context.Context, client pb.GNMIClient, setOps []*Operation) error {
	req, err := newSetRequest(setOps)
	if err != nil {
		return err
	}
	resp, err := client.Set(ctx, req)
	if err != nil {
		return err
	}
	if resp.Message != nil && codes.Code(resp.Message.Code) != codes.OK {
		return errors.New(resp.Message.Message)
	}
	// TODO: Iterate over SetResponse.Response for more detailed error message?

	return nil
}

// Subscribe sends a SubscribeRequest to the given client.
func Subscribe(ctx context.Context, client pb.GNMIClient, paths [][]string,
	respChan chan<- *pb.SubscribeResponse, errChan chan<- error) {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	stream, err := client.Subscribe(ctx)
	if err != nil {
		errChan <- err
		return
	}
	req, err := NewSubscribeRequest(paths)
	if err != nil {
		errChan <- err
		return
	}
	if err := stream.Send(req); err != nil {
		errChan <- err
		return
	}

	for {
		resp, err := stream.Recv()
		if err != nil {
			if err == io.EOF {
				return
			}
			errChan <- err
			return
		}
		respChan <- resp
	}
}

// LogSubscribeResponse logs update responses to stderr.
func LogSubscribeResponse(response *pb.SubscribeResponse) error {
	switch resp := response.Response.(type) {
	case *pb.SubscribeResponse_Error:
		return errors.New(resp.Error.Message)
	case *pb.SubscribeResponse_SyncResponse:
		if !resp.SyncResponse {
			return errors.New("initial sync failed")
		}
	case *pb.SubscribeResponse_Update:
		prefix := StrPath(resp.Update.Prefix)
		for _, update := range resp.Update.Update {
			fmt.Printf("%s = %s\n", path.Join(prefix, StrPath(update.Path)),
				StrUpdateVal(update))
		}
	}
	return nil
}
<commit_msg>gnmi: make StrVal() public<commit_after>// Copyright (c) 2017 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package gnmi

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"path"
	"strconv"

	pb "github.com/openconfig/gnmi/proto/gnmi"
	"google.golang.org/grpc/codes"
)

// Get sents a GetRequest to the given client.
func Get(ctx context.Context, client pb.GNMIClient, paths [][]string) error {
	req, err := NewGetRequest(paths)
	if err != nil {
		return err
	}
	resp, err := client.Get(ctx, req)
	if err != nil {
		return err
	}
	for _, notif := range resp.Notification {
		for _, update := range notif.Update {
			fmt.Printf("%s:\n", StrPath(update.Path))
			fmt.Println(StrUpdateVal(update))
		}
	}
	return nil
}

// Capabilities retuns the capabilities of the client.
func Capabilities(ctx context.Context, client pb.GNMIClient) error {
	resp, err := client.Capabilities(ctx, &pb.CapabilityRequest{})
	if err != nil {
		return err
	}
	fmt.Printf("Version: %s\n", resp.GNMIVersion)
	for _, mod := range resp.SupportedModels {
		fmt.Printf("SupportedModel: %s\n", mod)
	}
	for _, enc := range resp.SupportedEncodings {
		fmt.Printf("SupportedEncoding: %s\n", enc)
	}
	return nil
}

// val may be a path to a file or it may be json. First see if it is a
// file, if so return its contents, otherwise return val
func extractJSON(val string) []byte {
	jsonBytes, err := ioutil.ReadFile(val)
	if err != nil {
		jsonBytes = []byte(val)
	}
	return jsonBytes
}

// StrUpdateVal will return a string representing the value within the supplied update
func StrUpdateVal(u *pb.Update) string {
	if u.Value != nil {
		// Backwards compatibility with pre-v0.4 gnmi
		switch u.Value.Type {
		case pb.Encoding_JSON, pb.Encoding_JSON_IETF:
			return strJSON(u.Value.Value)
		case pb.Encoding_BYTES, pb.Encoding_PROTO:
			base64.StdEncoding.EncodeToString(u.Value.Value)
		case pb.Encoding_ASCII:
			return string(u.Value.Value)
		default:
			return string(u.Value.Value)
		}
	}
	return StrVal(u.Val)
}

// StrVal will return a string representing the supplied value
func StrVal(val *pb.TypedValue) string {
	switch v := val.GetValue().(type) {
	case *pb.TypedValue_StringVal:
		return v.StringVal
	case *pb.TypedValue_JsonIetfVal:
		return strJSON(v.JsonIetfVal)
	case *pb.TypedValue_JsonVal:
		return strJSON(v.JsonVal)
	case *pb.TypedValue_IntVal:
		return strconv.FormatInt(v.IntVal, 10)
	case *pb.TypedValue_UintVal:
		return strconv.FormatUint(v.UintVal, 10)
	case *pb.TypedValue_BoolVal:
		return strconv.FormatBool(v.BoolVal)
	case *pb.TypedValue_BytesVal:
		return base64.StdEncoding.EncodeToString(v.BytesVal)
	case *pb.TypedValue_DecimalVal:
		return strDecimal64(v.DecimalVal)
	case *pb.TypedValue_FloatVal:
		return strconv.FormatFloat(float64(v.FloatVal), 'g', -1, 32)
	case *pb.TypedValue_LeaflistVal:
		return strLeaflist(v.LeaflistVal)
	case *pb.TypedValue_AsciiVal:
		return v.AsciiVal
	case *pb.TypedValue_AnyVal:
		return v.AnyVal.String()
	default:
		panic(v)
	}
}

func strJSON(inJSON []byte) string {
	var out bytes.Buffer
	err := json.Indent(&out, inJSON, "", "  ")
	if err != nil {
		return fmt.Sprintf("(error unmarshalling json: %s)\n", err) + string(inJSON)
	}
	return out.String()
}

func strDecimal64(d *pb.Decimal64) string {
	var i, frac uint64
	if d.Precision > 0 {
		div := uint64(10)
		it := d.Precision - 1
		for it > 0 {
			div *= 10
			it--
		}
		i = d.Digits / div
		frac = d.Digits % div
	} else {
		i = d.Digits
	}
	return fmt.Sprintf("%d.%d", i, frac)
}

// strLeafList builds a human-readable form of a leaf-list. e.g. [1,2,3] or [a,b,c]
func strLeaflist(v *pb.ScalarArray) string {
	s := make([]string, 0, len(v.Element))
	sz := 2 // []

	// convert arbitrary TypedValues to string form
	for _, elm := range v.Element {
		str := StrVal(elm)
		s = append(s, str)
		sz += len(str) + 1 // %v + ,
	}

	b := make([]byte, sz)
	buf := bytes.NewBuffer(b)

	buf.WriteRune('[')
	for i := range v.Element {
		buf.WriteString(s[i])
		if i < len(v.Element)-1 {
			buf.WriteRune(',')
		}
	}
	buf.WriteRune(']')
	return buf.String()
}

func update(p *pb.Path, val string) *pb.Update {
	var v *pb.TypedValue
	switch p.Origin {
	case "":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_JsonIetfVal{JsonIetfVal: extractJSON(val)}}
	case "cli":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_AsciiVal{AsciiVal: val}}
	default:
		panic(fmt.Errorf("unexpected origin: %q", p.Origin))
	}

	return &pb.Update{Path: p, Val: v}
}

// Operation describes an gNMI operation.
type Operation struct {
	Type string
	Path []string
	Val  string
}

func newSetRequest(setOps []*Operation) (*pb.SetRequest, error) {
	req := &pb.SetRequest{}
	for _, op := range setOps {
		p, err := ParseGNMIElements(op.Path)
		if err != nil {
			return nil, err
		}

		switch op.Type {
		case "delete":
			req.Delete = append(req.Delete, p)
		case "update":
			req.Update = append(req.Update, update(p, op.Val))
		case "replace":
			req.Replace = append(req.Replace, update(p, op.Val))
		}
	}
	return req, nil
}

// Set sends a SetRequest to the given client.
func Set(ctx context.Context, client pb.GNMIClient, setOps []*Operation) error {
	req, err := newSetRequest(setOps)
	if err != nil {
		return err
	}
	resp, err := client.Set(ctx, req)
	if err != nil {
		return err
	}
	if resp.Message != nil && codes.Code(resp.Message.Code) != codes.OK {
		return errors.New(resp.Message.Message)
	}
	// TODO: Iterate over SetResponse.Response for more detailed error message?

	return nil
}

// Subscribe sends a SubscribeRequest to the given client.
func Subscribe(ctx context.Context, client pb.GNMIClient, paths [][]string,
	respChan chan<- *pb.SubscribeResponse, errChan chan<- error) {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	stream, err := client.Subscribe(ctx)
	if err != nil {
		errChan <- err
		return
	}
	req, err := NewSubscribeRequest(paths)
	if err != nil {
		errChan <- err
		return
	}
	if err := stream.Send(req); err != nil {
		errChan <- err
		return
	}

	for {
		resp, err := stream.Recv()
		if err != nil {
			if err == io.EOF {
				return
			}
			errChan <- err
			return
		}
		respChan <- resp
	}
}

// LogSubscribeResponse logs update responses to stderr.
func LogSubscribeResponse(response *pb.SubscribeResponse) error {
	switch resp := response.Response.(type) {
	case *pb.SubscribeResponse_Error:
		return errors.New(resp.Error.Message)
	case *pb.SubscribeResponse_SyncResponse:
		if !resp.SyncResponse {
			return errors.New("initial sync failed")
		}
	case *pb.SubscribeResponse_Update:
		prefix := StrPath(resp.Update.Prefix)
		for _, update := range resp.Update.Update {
			fmt.Printf("%s = %s\n", path.Join(prefix, StrPath(update.Path)),
				StrUpdateVal(update))
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package xlog

import "testing"

// BenchmarkArray1-12    	2000000000	         0.26 ns/op	       0 B/op	       0 allocs/op
func BenchmarkArray1(b *testing.B) {
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		var arr [1]int
		tmp := arr[:]
		tmp[0] = 100
	}
}

// BenchmarkArray1-12    	2000000000	         0.26 ns/op	       0 B/op	       0 allocs/op
func BenchmarkSlice1(b *testing.B) {
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		tmp := make([]int, 1, 1)
		tmp[0] = 100
	}
}
<commit_msg>add no-log benchmark<commit_after>package xlog

import "testing"

// BenchmarkArray1-12    	2000000000	         0.26 ns/op	       0 B/op	       0 allocs/op
func BenchmarkArray1(b *testing.B) {
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		var arr [1]int
		tmp := arr[:]
		tmp[0] = 100
	}
}

// BenchmarkArray1-12    	2000000000	         0.26 ns/op	       0 B/op	       0 allocs/op
func BenchmarkSlice1(b *testing.B) {
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		tmp := make([]int, 1, 1)
		tmp[0] = 100
	}
}

// BenchmarkNoLog-12    	50000000	        31.8 ns/op	      32 B/op	       1 allocs/op
func BenchmarkNoLog(b *testing.B) {
	SetLevel(LEVEL_WARN)
	log := GetLogger()

	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		log.Info("hahahhhhh %v", nil)
	}
}

// BenchmarkNoLog2-12    	500000000	         3.34 ns/op	       0 B/op	       0 allocs/op
func BenchmarkNoLog2(b *testing.B) {
	SetLevel(LEVEL_WARN)
	log := GetLogger()

	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		if log.IsInfoEnabled() {
			log.Info("hahahhhhh %v", nil)
		}
	}
}
<|endoftext|>


<commit_before>package server

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/bradleyfalzon/ghinstallation"
	"github.com/google/go-github/github"
	"github.com/haya14busa/reviewdog"
	"github.com/haya14busa/reviewdog/diff"
	"github.com/haya14busa/reviewdog/doghouse"
)

type DogHouse struct {
	client *http.Client
	req    *doghouse.CheckRequest
	gh     *github.Client
}

func New(req *doghouse.CheckRequest, privateKey []byte, integrationID int, c *http.Client) (*DogHouse, error) {
	dh := &DogHouse{client: c, req: req}
	if err := dh.setGitHubClient(privateKey, integrationID); err != nil {
		return nil, err
	}
	return dh, nil
}

func (dh *DogHouse) Check(ctx context.Context, req *doghouse.CheckRequest) (*doghouse.CheckResponse, error) {
	pr, _, err := dh.gh.PullRequests.Get(ctx, req.Owner, req.Repo, req.PullRequest)
	if err != nil {
		return nil, fmt.Errorf("failed to get pr: %v", err)
	}

	headBranch := pr.GetHead().GetRef()
	if headBranch == "" {
		return nil, fmt.Errorf("failed to get branch")
	}

	filediffs, err := dh.diff(ctx)
	if err != nil {
		return nil, fmt.Errorf("fail to parse diff: %v", err)
	}

	results := annotationsToCheckResults(req.Annotations)
	filtered := reviewdog.FilterCheck(results, filediffs, 1, "")
	checkRun, err := dh.postCheck(ctx, headBranch, filtered)
	if err != nil {
		return nil, err
	}
	res := &doghouse.CheckResponse{
		ReportURL: checkRun.GetHTMLURL(),
	}
	return res, nil
}

func (dh *DogHouse) postCheck(ctx context.Context, branch string, checks []*reviewdog.FilteredCheck) (*github.CheckRun, error) {
	var annotations []*github.CheckRunAnnotation
	for _, c := range checks {
		if !c.InDiff {
			continue
		}
		annotations = append(annotations, dh.toCheckRunAnnotation(c))
	}
	conclusion := "success"
	if len(annotations) > 0 {
		conclusion = "action_required"
	}
	name := "reviewdog"
	title := "reviewdog report"
	if dh.req.Name != "" {
		name = dh.req.Name
		title = fmt.Sprintf("reviewdog [%s] report", name)
	}
	opt := github.CreateCheckRunOptions{
		Name:        name,
		ExternalID:  github.String(name),
		HeadBranch:  branch,
		HeadSHA:     dh.req.SHA,
		Status:      github.String("completed"),
		Conclusion:  github.String(conclusion),
		CompletedAt: &github.Timestamp{time.Now()},
		Output: &github.CheckRunOutput{
			Title:       github.String(title),
			Summary:     github.String(dh.summary(checks)),
			Annotations: annotations,
		},
	}

	checkRun, _, err := dh.gh.Checks.CreateCheckRun(ctx, dh.req.Owner, dh.req.Repo, opt)
	if err != nil {
		return nil, err
	}
	return checkRun, nil
}

func (dh *DogHouse) summary(checks []*reviewdog.FilteredCheck) string {
	var lines []string
	lines = append(lines, "reported by [reviewdog](https://github.com/haya14busa/reviewdog) :dog:")

	var findings []*reviewdog.FilteredCheck
	var filteredFindings []*reviewdog.FilteredCheck
	for _, c := range checks {
		if c.InDiff {
			findings = append(findings, c)
		} else {
			filteredFindings = append(filteredFindings, c)
		}
	}
	lines = append(lines, dh.summaryFindings("Findings", findings)...)
	lines = append(lines, dh.summaryFindings("Filtered Findings", filteredFindings)...)

	return strings.Join(lines, "\n")
}

func (dh *DogHouse) summaryFindings(name string, checks []*reviewdog.FilteredCheck) []string {
	var lines []string
	lines = append(lines, "")
	lines = append(lines, fmt.Sprintf("%s (%d)", name, len(checks)))
	lines = append(lines, "")
	for _, c := range checks {
		lines = append(lines, dh.buildFindingLink(c))
	}
	lines = append(lines, "")
	return lines
}

func (dh *DogHouse) buildFindingLink(c *reviewdog.FilteredCheck) string {
	if c.Path == "" {
		return c.Message
	}
	loc := c.Path
	link := fmt.Sprintf("%s", dh.brobHRef(c.Path))
	if c.Lnum != 0 {
		loc = fmt.Sprintf("%s:%d", loc, c.Lnum)
		link = fmt.Sprintf("%s#L%d", link, c.Lnum)
	}
	if c.Col != 0 {
		loc = fmt.Sprintf("%s:%d", loc, c.Col)
	}
	return fmt.Sprintf("[%s](%s): %s", loc, link, c.Message)
}

func (dh *DogHouse) toCheckRunAnnotation(c *reviewdog.FilteredCheck) *github.CheckRunAnnotation {
	a := &github.CheckRunAnnotation{
		FileName:     github.String(c.Path),
		BlobHRef:     github.String(dh.brobHRef(c.Path)),
		StartLine:    github.Int(c.Lnum),
		EndLine:      github.Int(c.Lnum),
		WarningLevel: github.String("warning"),
		Message:      github.String(c.Message),
	}
	if dh.req.Name != "" {
		a.Title = github.String(fmt.Sprintf("[%s] %s#L%d", dh.req.Name, c.Path, c.Lnum))
	}
	if s := strings.Join(c.Lines, "\n"); s != "" {
		a.RawDetails = github.String(s)
	}
	return a
}

func (dh *DogHouse) brobHRef(path string) string {
	return fmt.Sprintf("http://github.com/%s/%s/blob/%s/%s", dh.req.Owner, dh.req.Repo, dh.req.SHA, path)
}

func (dh *DogHouse) setGitHubClient(privateKey []byte, integrationID int) error {
	itr, err := ghinstallation.New(dh.client.Transport, integrationID, dh.req.InstallationID, privateKey)
	if err != nil {
		return fmt.Errorf("failed to create gh transport: %v", err)
	}
	dh.client.Transport = itr
	dh.gh = github.NewClient(dh.client)
	return nil
}

func (dh *DogHouse) diff(ctx context.Context) ([]*diff.FileDiff, error) {
	d, err := dh.rawDiff(ctx)
	if err != nil {
		return nil, err
	}
	filediffs, err := diff.ParseMultiFile(bytes.NewReader(d))
	if err != nil {
		return nil, fmt.Errorf("fail to parse diff: %v", err)
	}
	return filediffs, nil
}

func (dh *DogHouse) rawDiff(ctx context.Context) ([]byte, error) {
	opt := github.RawOptions{Type: github.Diff}
	d, _, err := dh.gh.PullRequests.GetRaw(ctx, dh.req.Owner, dh.req.Repo, dh.req.PullRequest, opt)
	if err != nil {
		return nil, err
	}
	return []byte(d), nil
}

func annotationsToCheckResults(as []*doghouse.Annotation) []*reviewdog.CheckResult {
	cs := make([]*reviewdog.CheckResult, 0, len(as))
	for _, a := range as {
		cs = append(cs, &reviewdog.CheckResult{
			Path:    a.Path,
			Lnum:    a.Line,
			Message: a.Message,
			Lines:   strings.Split(a.RawMessage, "\n"),
		})
	}
	return cs
}
<commit_msg>use neutral for now<commit_after>package server

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/bradleyfalzon/ghinstallation"
	"github.com/google/go-github/github"
	"github.com/haya14busa/reviewdog"
	"github.com/haya14busa/reviewdog/diff"
	"github.com/haya14busa/reviewdog/doghouse"
)

type DogHouse struct {
	client *http.Client
	req    *doghouse.CheckRequest
	gh     *github.Client
}

func New(req *doghouse.CheckRequest, privateKey []byte, integrationID int, c *http.Client) (*DogHouse, error) {
	dh := &DogHouse{client: c, req: req}
	if err := dh.setGitHubClient(privateKey, integrationID); err != nil {
		return nil, err
	}
	return dh, nil
}

func (dh *DogHouse) Check(ctx context.Context, req *doghouse.CheckRequest) (*doghouse.CheckResponse, error) {
	pr, _, err := dh.gh.PullRequests.Get(ctx, req.Owner, req.Repo, req.PullRequest)
	if err != nil {
		return nil, fmt.Errorf("failed to get pr: %v", err)
	}

	headBranch := pr.GetHead().GetRef()
	if headBranch == "" {
		return nil, fmt.Errorf("failed to get branch")
	}

	filediffs, err := dh.diff(ctx)
	if err != nil {
		return nil, fmt.Errorf("fail to parse diff: %v", err)
	}

	results := annotationsToCheckResults(req.Annotations)
	filtered := reviewdog.FilterCheck(results, filediffs, 1, "")
	checkRun, err := dh.postCheck(ctx, headBranch, filtered)
	if err != nil {
		return nil, err
	}
	res := &doghouse.CheckResponse{
		ReportURL: checkRun.GetHTMLURL(),
	}
	return res, nil
}

func (dh *DogHouse) postCheck(ctx context.Context, branch string, checks []*reviewdog.FilteredCheck) (*github.CheckRun, error) {
	var annotations []*github.CheckRunAnnotation
	for _, c := range checks {
		if !c.InDiff {
			continue
		}
		annotations = append(annotations, dh.toCheckRunAnnotation(c))
	}
	conclusion := "success"
	if len(annotations) > 0 {
		// Use "neutral" for now because of the bug.
		// https://platform.github.community/t/checks-api-check-contents-are-replaced-by-latest-check-with-different-check-name-in-check-page/5902?u=haya14busa
		// conclusion = "action_required"
		conclusion = "neutral"
	}
	name := "reviewdog"
	title := "reviewdog report"
	if dh.req.Name != "" {
		name = dh.req.Name
		title = fmt.Sprintf("reviewdog [%s] report", name)
	}
	opt := github.CreateCheckRunOptions{
		Name:        name,
		ExternalID:  github.String(name),
		HeadBranch:  branch,
		HeadSHA:     dh.req.SHA,
		Status:      github.String("completed"),
		Conclusion:  github.String(conclusion),
		CompletedAt: &github.Timestamp{time.Now()},
		Output: &github.CheckRunOutput{
			Title:       github.String(title),
			Summary:     github.String(dh.summary(checks)),
			Annotations: annotations,
		},
	}

	checkRun, _, err := dh.gh.Checks.CreateCheckRun(ctx, dh.req.Owner, dh.req.Repo, opt)
	if err != nil {
		return nil, err
	}
	return checkRun, nil
}

func (dh *DogHouse) summary(checks []*reviewdog.FilteredCheck) string {
	var lines []string
	lines = append(lines, "reported by [reviewdog](https://github.com/haya14busa/reviewdog) :dog:")

	var findings []*reviewdog.FilteredCheck
	var filteredFindings []*reviewdog.FilteredCheck
	for _, c := range checks {
		if c.InDiff {
			findings = append(findings, c)
		} else {
			filteredFindings = append(filteredFindings, c)
		}
	}
	lines = append(lines, dh.summaryFindings("Findings", findings)...)
	lines = append(lines, dh.summaryFindings("Filtered Findings", filteredFindings)...)

	return strings.Join(lines, "\n")
}

func (dh *DogHouse) summaryFindings(name string, checks []*reviewdog.FilteredCheck) []string {
	var lines []string
	lines = append(lines, "")
	lines = append(lines, fmt.Sprintf("%s (%d)", name, len(checks)))
	lines = append(lines, "")
	for _, c := range checks {
		lines = append(lines, dh.buildFindingLink(c))
	}
	lines = append(lines, "")
	return lines
}

func (dh *DogHouse) buildFindingLink(c *reviewdog.FilteredCheck) string {
	if c.Path == "" {
		return c.Message
	}
	loc := c.Path
	link := fmt.Sprintf("%s", dh.brobHRef(c.Path))
	if c.Lnum != 0 {
		loc = fmt.Sprintf("%s:%d", loc, c.Lnum)
		link = fmt.Sprintf("%s#L%d", link, c.Lnum)
	}
	if c.Col != 0 {
		loc = fmt.Sprintf("%s:%d", loc, c.Col)
	}
	return fmt.Sprintf("[%s](%s): %s", loc, link, c.Message)
}

func (dh *DogHouse) toCheckRunAnnotation(c *reviewdog.FilteredCheck) *github.CheckRunAnnotation {
	a := &github.CheckRunAnnotation{
		FileName:     github.String(c.Path),
		BlobHRef:     github.String(dh.brobHRef(c.Path)),
		StartLine:    github.Int(c.Lnum),
		EndLine:      github.Int(c.Lnum),
		WarningLevel: github.String("warning"),
		Message:      github.String(c.Message),
	}
	if dh.req.Name != "" {
		a.Title = github.String(fmt.Sprintf("[%s] %s#L%d", dh.req.Name, c.Path, c.Lnum))
	}
	if s := strings.Join(c.Lines, "\n"); s != "" {
		a.RawDetails = github.String(s)
	}
	return a
}

func (dh *DogHouse) brobHRef(path string) string {
	return fmt.Sprintf("http://github.com/%s/%s/blob/%s/%s", dh.req.Owner, dh.req.Repo, dh.req.SHA, path)
}

func (dh *DogHouse) setGitHubClient(privateKey []byte, integrationID int) error {
	itr, err := ghinstallation.New(dh.client.Transport, integrationID, dh.req.InstallationID, privateKey)
	if err != nil {
		return fmt.Errorf("failed to create gh transport: %v", err)
	}
	dh.client.Transport = itr
	dh.gh = github.NewClient(dh.client)
	return nil
}

func (dh *DogHouse) diff(ctx context.Context) ([]*diff.FileDiff, error) {
	d, err := dh.rawDiff(ctx)
	if err != nil {
		return nil, err
	}
	filediffs, err := diff.ParseMultiFile(bytes.NewReader(d))
	if err != nil {
		return nil, fmt.Errorf("fail to parse diff: %v", err)
	}
	return filediffs, nil
}

func (dh *DogHouse) rawDiff(ctx context.Context) ([]byte, error) {
	opt := github.RawOptions{Type: github.Diff}
	d, _, err := dh.gh.PullRequests.GetRaw(ctx, dh.req.Owner, dh.req.Repo, dh.req.PullRequest, opt)
	if err != nil {
		return nil, err
	}
	return []byte(d), nil
}

func annotationsToCheckResults(as []*doghouse.Annotation) []*reviewdog.CheckResult {
	cs := make([]*reviewdog.CheckResult, 0, len(as))
	for _, a := range as {
		cs = append(cs, &reviewdog.CheckResult{
			Path:    a.Path,
			Lnum:    a.Line,
			Message: a.Message,
			Lines:   strings.Split(a.RawMessage, "\n"),
		})
	}
	return cs
}
<|endoftext|>


<commit_before>package main

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

	"github.com/mrjones/oauth"
)

func main() {
	var consumerKey *string = flag.String(
		"consumerkey",
		"",
		"Consumer Key from NetFlix. See: http://developer.netflix.com/apps/mykeys")

	var consumerSecret *string = flag.String(
		"consumersecret",
		"",
		"Consumer Key from NetFlix. See: http://developer.netflix.com/apps/mykeys")

	var appName *string = flag.String(
		"appname",
		"",
		"Application name registered with NetFlix.")

	var debug *bool = flag.Bool(
		"debug",
		false,
		"If true, print debugging information")

	flag.Parse()

	if len(*consumerKey) == 0 || len(*consumerSecret) == 0 || len(*appName) == 0{
		fmt.Println("You must set the --consumerkey, --consumersecret and --appname flags.")
		os.Exit(1)
	}

	c := oauth.NewConsumer(
		*consumerKey,
		*consumerSecret,
		oauth.ServiceProvider{
			RequestTokenUrl:   "http://api-public.netflix.com/oauth/request_token",
			AuthorizeTokenUrl: "https://api-user.netflix.com/oauth/login",
			AccessTokenUrl:    "http://api-public.netflix.com/oauth/access_token",
		})

	// See #4 here:
	// http://josephsmarr.com/2008/10/01/using-netflixs-new-api-a-step-by-step-guide/
	c.AdditionalAuthorizationUrlParams = map[string]string{
		"application_name":   *appName,
		"oauth_consumer_key": *consumerKey,
	}

	c.Debug(*debug)

	requestToken, url, err := c.GetRequestTokenAndUrl("oob")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("(1) Go to: " + url)
	fmt.Println("(2) Grant access, you should get back a verification code.")
	fmt.Println("(3) Enter that verification code here: ")

	verificationCode := ""
	fmt.Scanln(&verificationCode)

	accessToken, err := c.AuthorizeToken(requestToken, verificationCode)
	if err != nil {
		log.Fatal(err)
	}

	response, err := c.Get(
		"http://api-public.netflix.com/users/current",
		map[string]string{},
		accessToken)
	if err != nil {
		log.Fatal(err)
	}
	defer response.Body.Close()

	bits, err := ioutil.ReadAll(response.Body)
	fmt.Println("Your NetFlix profile: " + string(bits))

	// TODO(mrjones): get real subscriberid

	response, err = c.Get(
		"http://api-public.netflix.com/users/T1jnI5Pil972U_d8VjxvgavhX62vj4sLVgKzk5IVzKza4-/recommendations",
		map[string]string{"max_results": "1", "start_index": "0"},
		accessToken)
	if err != nil {
		log.Fatal(err)
	}
	defer response.Body.Close()

	bits, err = ioutil.ReadAll(response.Body)
	fmt.Println("NetFlix recomments: " + string(bits))
}
<commit_msg>note for running netflix.go<commit_after>// go run examples/netflix/netflix.go --consumerkey <key> --consumersecret <secret> --appname <appname>
package main

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

	"github.com/mrjones/oauth"
)

func main() {
	var consumerKey *string = flag.String(
		"consumerkey",
		"",
		"Consumer Key from NetFlix. See: http://developer.netflix.com/apps/mykeys")

	var consumerSecret *string = flag.String(
		"consumersecret",
		"",
		"Consumer Key from NetFlix. See: http://developer.netflix.com/apps/mykeys")

	var appName *string = flag.String(
		"appname",
		"",
		"Application name registered with NetFlix.")

	var debug *bool = flag.Bool(
		"debug",
		false,
		"If true, print debugging information")

	flag.Parse()

	if len(*consumerKey) == 0 || len(*consumerSecret) == 0 || len(*appName) == 0{
		fmt.Println("You must set the --consumerkey, --consumersecret and --appname flags.")
		os.Exit(1)
	}

	c := oauth.NewConsumer(
		*consumerKey,
		*consumerSecret,
		oauth.ServiceProvider{
			RequestTokenUrl:   "http://api-public.netflix.com/oauth/request_token",
			AuthorizeTokenUrl: "https://api-user.netflix.com/oauth/login",
			AccessTokenUrl:    "http://api-public.netflix.com/oauth/access_token",
		})

	// See #4 here:
	// http://josephsmarr.com/2008/10/01/using-netflixs-new-api-a-step-by-step-guide/
	c.AdditionalAuthorizationUrlParams = map[string]string{
		"application_name":   *appName,
		"oauth_consumer_key": *consumerKey,
	}

	c.Debug(*debug)

	requestToken, url, err := c.GetRequestTokenAndUrl("oob")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("(1) Go to: " + url)
	fmt.Println("(2) Grant access, you should get back a verification code.")
	fmt.Println("(3) Enter that verification code here: ")

	verificationCode := ""
	fmt.Scanln(&verificationCode)

	accessToken, err := c.AuthorizeToken(requestToken, verificationCode)
	if err != nil {
		log.Fatal(err)
	}

	response, err := c.Get(
		"http://api-public.netflix.com/users/current",
		map[string]string{},
		accessToken)
	if err != nil {
		log.Fatal(err)
	}
	defer response.Body.Close()

	bits, err := ioutil.ReadAll(response.Body)
	fmt.Println("Your NetFlix profile: " + string(bits))

	// TODO(mrjones): get real subscriberid

	response, err = c.Get(
		"http://api-public.netflix.com/users/T1jnI5Pil972U_d8VjxvgavhX62vj4sLVgKzk5IVzKza4-/recommendations",
		map[string]string{"max_results": "1", "start_index": "0"},
		accessToken)
	if err != nil {
		log.Fatal(err)
	}
	defer response.Body.Close()

	bits, err = ioutil.ReadAll(response.Body)
	fmt.Println("NetFlix recomments: " + string(bits))
}
<|endoftext|>


<commit_before>package socket

import (
	"log"

	"github.com/sayden/docker-commander/Godeps/_workspace/src/github.com/samalba/dockerclient"
	"github.com/sayden/docker-commander/discovery"
	"github.com/sayden/docker-commander/entities"
	"github.com/sayden/docker-commander/swarm"
)

func getClusterInfo(s swarm.Swarm) (*dockerclient.Info, error) {
	// Cluster info
	i, err := s.ListInfo()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	return &i, nil
}

func getAgentsList(i discovery.InfoService) ([]entities.Agent, error) {
	//Get every host
	hs, err := i.ListHosts()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	//Map byte Nodes to DockerClientNodes
	var agents []entities.Agent
	for _, h := range hs {
		a := entities.Agent{
			IP: h.IP,
		}

		agents = append(agents, a)
	}

	return agents, nil
}

func addContainersForEachAgent(s swarm.Swarm, ag *[]entities.Agent) error {
	if len(*ag) == 0 {
		log.Println("ERROR: There are no agents in ag parameter")
	}

	agents := *ag

	//Foreach host, get its containers
	for i := range agents {
		h := &agents[i]
		cs, err := s.ListContainers()
		if err != nil {
			return err
		}

		h.Containers = cs
	}

	return nil
}

// GetContainers uses a Swarm client to return some ip's containers
func GetContainers(s swarm.Swarm, ip string) (*[]dockerclient.Container, error) {
	cs, err := s.ListContainers()
	if err != nil {
		return &[]dockerclient.Container{}, err
	}

	return &cs, nil
}

func GetImages(s swarm.Swarm, ip string) (*[]dockerclient.Image, error) {
	is, err := s.ListImages()
	if err != nil {
		return &[]dockerclient.Image{}, err
	}

	return &is, nil
}

func addImagesForEachAgent(s swarm.Swarm, ag *[]entities.Agent) error {
	if len(*ag) == 0 {
		log.Println("ERROR: There are no agents in ag parameter")
	}

	agents := *ag

	//Foreach host, get its containers
	for i := range agents {
		h := &agents[i]
		is, err := s.ListImages()
		if err != nil {
			return err
		}

		h.Images = is
	}

	return nil
}

// GetFullInfo joins all available info of the cluster in a single response
func GetFullInfo(s swarm.Swarm, i discovery.InfoService) (entities.Overall, error) {
	cluster, err := getClusterInfo(s)
	if err != nil {
		log.Println(err)
		return entities.Overall{}, err
	}
	agentsNodes, err := getAgentsList(i)
	if err != nil {
		log.Println(err)
		return entities.Overall{}, err
	}

	err = addContainersForEachAgent(s, &agentsNodes)
	if err != nil {
		return entities.Overall{}, err
	}

	err = addImagesForEachAgent(s, &agentsNodes)
	if err != nil {
		return entities.Overall{}, err
	}

	return entities.Overall{
		Cluster: *cluster,
		Agents:  agentsNodes,
	}, nil
}
<commit_msg>no logging in handlers. return errors<commit_after>package socket

import (
	"errors"

	"github.com/sayden/docker-commander/Godeps/_workspace/src/github.com/samalba/dockerclient"
	"github.com/sayden/docker-commander/discovery"
	"github.com/sayden/docker-commander/entities"
	"github.com/sayden/docker-commander/swarm"
)

func getClusterInfo(s swarm.Swarm) (*dockerclient.Info, error) {
	// Cluster info
	i, err := s.ListInfo()
	if err != nil {
		return nil, err
	}

	return &i, nil
}

func getAgentsList(i discovery.InfoService) ([]entities.Agent, error) {
	//Get every host
	hs, err := i.ListHosts()
	if err != nil {
		return nil, err
	}

	//Map byte Nodes to DockerClientNodes
	var agents []entities.Agent
	for _, h := range hs {
		a := entities.Agent{
			IP: h.IP,
		}

		agents = append(agents, a)
	}

	return agents, nil
}

func addContainersForEachAgent(s swarm.Swarm, ag *[]entities.Agent) error {
	if len(*ag) == 0 {
		err := errors.New("ERROR: There are no agents in ag parameter")
		return err
	}

	agents := *ag

	//Foreach host, get its containers
	for i := range agents {
		h := &agents[i]
		cs, err := s.ListContainers()
		if err != nil {
			return err
		}

		h.Containers = cs
	}

	return nil
}

// GetContainers uses a Swarm client to return some ip's containers
func GetContainers(s swarm.Swarm, ip string) (*[]dockerclient.Container, error) {
	cs, err := s.ListContainers()
	if err != nil {
		return &[]dockerclient.Container{}, err
	}

	return &cs, nil
}

//GetImages returns images associated with a host ip or error
func GetImages(s swarm.Swarm, ip string) (*[]dockerclient.Image, error) {
	is, err := s.ListImages()
	if err != nil {
		return &[]dockerclient.Image{}, err
	}

	return &is, nil
}

func addImagesForEachAgent(s swarm.Swarm, ag *[]entities.Agent) error {
	if len(*ag) == 0 {
		err := errors.New("ERROR: There are no agents in ag parameter")
		return err
	}

	agents := *ag

	//Foreach host, get its containers
	for i := range agents {
		h := &agents[i]
		is, err := s.ListImages()
		if err != nil {
			return err
		}

		h.Images = is
	}

	return nil
}

// GetFullInfo joins all available info of the cluster in a single response
func GetFullInfo(s swarm.Swarm, i discovery.InfoService) (entities.Overall, error) {
	cluster, err := getClusterInfo(s)
	if err != nil {
		return entities.Overall{}, err
	}
	agentsNodes, err := getAgentsList(i)
	if err != nil {
		return entities.Overall{}, err
	}

	err = addContainersForEachAgent(s, &agentsNodes)
	if err != nil {
		return entities.Overall{}, err
	}

	err = addImagesForEachAgent(s, &agentsNodes)
	if err != nil {
		return entities.Overall{}, err
	}

	return entities.Overall{
		Cluster: *cluster,
		Agents:  agentsNodes,
	}, nil
}
<|endoftext|>


<commit_before>package ws

import (
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"hash"
	"math/rand"
	"net/http"
	"net/textproto"
	"net/url"
	"strings"
	"sync"
)

const (
	nonceSize  = 24
	acceptSize = 28
	shaSumSize = 20
)

var (
	headerUpgrade       = textproto.CanonicalMIMEHeaderKey("Upgrade")
	headerConnection    = textproto.CanonicalMIMEHeaderKey("Connection")
	headerHost          = textproto.CanonicalMIMEHeaderKey("Host")
	headerOrigin        = textproto.CanonicalMIMEHeaderKey("Origin")
	headerSecVersion    = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Version")
	headerSecProtocol   = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Protocol")
	headerSecExtensions = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Extensions")
	headerSecKey        = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Key")
	headerSecAccept     = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Accept")
)

var ErrBadNonce = fmt.Errorf("nonce size is not %d", nonceSize)

var WebSocketMagic = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")

type request struct {
	http.Request
	Nonce      [nonceSize]byte
	Protocols  []string
	Extensions []string
}

func (req *request) Reset(urlstr string, headers http.Header, protocols, extensions []string) error {
	u, err := url.ParseRequestURI(urlstr)
	if err != nil {
		return err
	}

	req.URL = u

	newNonce(req.Nonce[:])
	req.Header.Set(headerSecKey, string(req.Nonce[:]))

	req.Protocols = protocols
	if protocols != nil {
		req.Header.Set(headerSecProtocol, strings.Join(protocols, ", "))
	}

	req.Extensions = extensions
	if extensions != nil {
		req.Header.Set(headerSecExtensions, strings.Join(extensions, ", "))
	}

	req.Header.Set("User-Agent", "") // Disable default user-agent header.

	if headers != nil {
		for k, v := range headers {
			req.Header[k] = v
		}
	}

	return nil
}

var requestPool sync.Pool

func getRequest() *request {
	if req := requestPool.Get(); req != nil {
		return req.(*request)
	}
	return newCommonRequest()
}

func putRequest(req *request) {
	req.URL = nil
	req.Protocols = nil
	req.Extensions = nil

	for k := range req.Header {
		switch k {
		case headerUpgrade, headerConnection, headerSecVersion:
			// leave common headers
		default:
			delete(req.Header, k)
		}
	}

	requestPool.Put(req)
}

func newCommonRequest() *request {
	req := &request{
		Request: http.Request{
			Header: make(http.Header),
		},
	}

	req.Header.Set(headerUpgrade, "websocket")
	req.Header.Set(headerConnection, "Upgrade")
	req.Header.Set(headerSecVersion, "13")

	return req
}

var sha1Pool sync.Pool

func acquireSha1() hash.Hash {
	if h := sha1Pool.Get(); h != nil {
		return h.(hash.Hash)
	}
	return sha1.New()
}

func releaseSha1(h hash.Hash) {
	h.Reset()
	sha1Pool.Put(h)
}

// todo bench put expect to req as array
func checkNonce(accept string, nonce [nonceSize]byte) bool {
	if len(accept) != 28 {
		return false
	}

	expect := makeAccept(nonce[:])

	return string(expect) == accept
}

//const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
//
//func newNonce(dest []byte) {
//	for i := 0; i < 22; i++ {
//		dest[i] = alphabet[rand.Intn(len(alphabet))]
//	}
//	dest[22] = '='
//	dest[23] = '='
//}

func randBytes(n int) []byte {
	bts := make([]byte, n)
	if _, err := rand.Read(bts); err != nil {
		panic(fmt.Sprintf("rand read error: %s", err))
	}
	return bts
}

func newNonce(dest []byte) {
	base64.StdEncoding.Encode(dest, randBytes(16))
}

func makeAccept(nonce []byte) []byte {
	bts := make([]byte, 0, acceptSize+shaSumSize)
	n := putAccept(nonce, bts)
	return bts[:n]
}

func putAccept(nonce, buf []byte) int {
	if cap(buf) < acceptSize+shaSumSize {
		panic(fmt.Sprintf("buffer cap is %d; want at least %d", len(buf), acceptSize+shaSumSize))
	}
	if len(nonce) != nonceSize {
		panic(fmt.Sprintf("nonce size is %d; want %d", len(nonce), nonceSize))
	}

	sha := acquireSha1()
	defer releaseSha1(sha)

	sha.Write(nonce)
	sha.Write(WebSocketMagic)

	buf = buf[:acceptSize]
	sum := sha.Sum(buf[acceptSize:])

	base64.StdEncoding.Encode(buf, sum)

	return acceptSize
}
<commit_msg>reduce allocations in makeAccept<commit_after>package ws

import (
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"hash"
	"math/rand"
	"net/http"
	"net/textproto"
	"net/url"
	"reflect"
	"strings"
	"sync"
	"unsafe"
)

const (
	// RFC6455: The value of this header field MUST be a nonce consisting of a
	// randomly selected 16-byte value that has been base64-encoded (see
	// Section 4 of [RFC4648]).  The nonce MUST be selected randomly for each
	// connection.
	nonceKeySize = 16
	nonceSize    = 24 // base64.StdEncoding.EncodedLen(nonceKeySize)

	// RFC6455: The value of this header field is constructed by concatenating
	// /key/, defined above in step 4 in Section 4.2.2, with the string
	// "258EAFA5- E914-47DA-95CA-C5AB0DC85B11", taking the SHA-1 hash of this
	// concatenated value to obtain a 20-byte value and base64- encoding (see
	// Section 4 of [RFC4648]) this 20-byte hash.
	acceptSize = 28 // base64.StdEncoding.EncodedLen(sha1.Size)
)

var (
	headerUpgrade       = textproto.CanonicalMIMEHeaderKey("Upgrade")
	headerConnection    = textproto.CanonicalMIMEHeaderKey("Connection")
	headerHost          = textproto.CanonicalMIMEHeaderKey("Host")
	headerOrigin        = textproto.CanonicalMIMEHeaderKey("Origin")
	headerSecVersion    = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Version")
	headerSecProtocol   = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Protocol")
	headerSecExtensions = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Extensions")
	headerSecKey        = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Key")
	headerSecAccept     = textproto.CanonicalMIMEHeaderKey("Sec-Websocket-Accept")
)

var ErrBadNonce = fmt.Errorf("nonce size is not %d", nonceSize)

var WebSocketMagic = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")

type request struct {
	http.Request
	Nonce      [nonceSize]byte
	Protocols  []string
	Extensions []string
}

func (req *request) Reset(urlstr string, headers http.Header, protocols, extensions []string) error {
	u, err := url.ParseRequestURI(urlstr)
	if err != nil {
		return err
	}

	req.URL = u

	newNonce(req.Nonce[:])
	req.Header.Set(headerSecKey, string(req.Nonce[:]))

	req.Protocols = protocols
	if protocols != nil {
		req.Header.Set(headerSecProtocol, strings.Join(protocols, ", "))
	}

	req.Extensions = extensions
	if extensions != nil {
		req.Header.Set(headerSecExtensions, strings.Join(extensions, ", "))
	}

	req.Header.Set("User-Agent", "") // Disable default user-agent header.

	if headers != nil {
		for k, v := range headers {
			req.Header[k] = v
		}
	}

	return nil
}

var requestPool sync.Pool

func getRequest() *request {
	if req := requestPool.Get(); req != nil {
		return req.(*request)
	}
	return newCommonRequest()
}

func putRequest(req *request) {
	req.URL = nil
	req.Protocols = nil
	req.Extensions = nil

	for k := range req.Header {
		switch k {
		case headerUpgrade, headerConnection, headerSecVersion:
			// leave common headers
		default:
			delete(req.Header, k)
		}
	}

	requestPool.Put(req)
}

func newCommonRequest() *request {
	req := &request{
		Request: http.Request{
			Header: make(http.Header),
		},
	}

	req.Header.Set(headerUpgrade, "websocket")
	req.Header.Set(headerConnection, "Upgrade")
	req.Header.Set(headerSecVersion, "13")

	return req
}

var sha1Pool sync.Pool

func acquireSha1() hash.Hash {
	if h := sha1Pool.Get(); h != nil {
		return h.(hash.Hash)
	}
	return sha1.New()
}

func releaseSha1(h hash.Hash) {
	h.Reset()
	sha1Pool.Put(h)
}

// todo bench put expect to req as array
func checkNonce(accept string, nonce [nonceSize]byte) bool {
	if len(accept) != acceptSize {
		return false
	}

	expect := makeAccept(nonce[:])

	return string(expect) == accept
}

//const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
//
//func newNonce(dest []byte) {
//	for i := 0; i < 22; i++ {
//		dest[i] = alphabet[rand.Intn(len(alphabet))]
//	}
//	dest[22] = '='
//	dest[23] = '='
//}

func randBytes(n int) []byte {
	bts := make([]byte, n)
	if _, err := rand.Read(bts); err != nil {
		panic(fmt.Sprintf("rand read error: %s", err))
	}
	return bts
}

func newNonce(dest []byte) {
	base64.StdEncoding.Encode(dest, randBytes(nonceKeySize))
}

func makeAccept(nonce []byte) []byte {
	accept := make([]byte, acceptSize)
	putAccept(nonce, accept)
	return accept
}

// putAccept generates accept bytes and puts them into p.
// Given buffer should be exactly acceptSize bytes. If not putAccept will panic.
func putAccept(nonce, p []byte) {
	if len(nonce) != nonceSize {
		panic(fmt.Sprintf("nonce size is %d; want %d", len(nonce), nonceSize))
	}
	if len(p) != acceptSize {
		panic(fmt.Sprintf("buffer size is %d; want %d", len(p), acceptSize))
	}

	var b [sha1.Size]byte
	bh := uintptr(unsafe.Pointer(&b))
	bts := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data: bh, Len: 0, Cap: sha1.Size}))

	sha := acquireSha1()
	defer releaseSha1(sha)

	sha.Write(nonce)
	sha.Write(WebSocketMagic)
	sum := sha.Sum(bts)

	base64.StdEncoding.Encode(p, sum)
}
<|endoftext|>


<commit_before>package gotumblr

import (
		"net/url"
		"net/http"
		"io/ioutil"
		"encoding/json"
		"github.com/kurrik/oauth1a"
		)

//Make queries to the Tumblr API through TumblrRequest
type TumblrRequest struct {
	service *oauth1a.Service
	userConfig *oauth1a.UserConfig
	host string
}

//Initializes the TumblrRequest.
//consumerKey is the consumer key of your Tumblr Application
//consumerSecret is the consumer secret of your Tumblr Application
//callbackUrl is the callback URL of your Tumblr Application
//oauthToken is the user specific token, received from the /access_token endpoint
//oauthSecret is the user specific secret, received from the /access_token endpoint
//host is the host that you are tryng to send information to (e.g. http://api.tumblr.com)
func NewTumblrRequest(consumerKey, consumerSecret, oauthToken, oauthSecret, callbackUrl, host string) *TumblrRequest {
	service := &oauth1a.Service{
		RequestURL:   "http://www.tumblr.com/oauth/request_token",
		AuthorizeURL: "http://www.rumblr.com/oauth/authorize",
		AccessURL:    "http://www.tumblr.com/oauth/access_token",
		ClientConfig: &oauth1a.ClientConfig{
			ConsumerKey:    consumerKey,
			ConsumerSecret: consumerSecret,
			CallbackURL:    callbackUrl,
	    },
		Signer: new(oauth1a.HmacSha1Signer),
	}
	userConfig := oauth1a.NewAuthorizedConfig(oauthToken, oauthSecret)
	return &TumblrRequest{service, userConfig, host}
}

//Make a GET request to the API with properly formatted parameters
//url: the url you are making the request to
//params: the parameters needed for the request
func (tr *TumblrRequest) Get(url string, params map[string]string) map[string]interface{} {
	full_url := tr.host + url
	if len(params) != 0 {
		values := url.Values{}
		for key, value := range params {
			values.Set(key, value)
			full_url = full_url + "?" + values.Encode()
		}
	}
	httpRequest, err := http.NewRequest("GET", full_url, nil)
	if err != nil {
		fmt.Println(err)
	}
	tr.service.Sign(httpRequest, tr.userConfig)
	var httpResponse *http.Response
	httpClient := new(http.Client)
	httpResponse, err2 := httpClient.Do(httpRequest)
	if err2 != nil {
		fmt.Println(err2)
	}
	defer httpResponse.Body.Close()
	body, err3 := ioutil.ReadAll(httpResponse.Body)
	if err3 != nil {
		fmt.Println(err3)
	}
	return tr.JsonParse(body)
}

//Makes a POST request to the API, allows for multipart data uploads
//url: the url you are making the request to
//params: all the parameters needed for the request
//files: list of files
func (tr *TumblrRequest) Post(url string, params map[string]string, files []string) map[string]interface{} {

}

//Parse JSON response.
//content: the content returned from the web request to be parsed as JSON
func (tr *TumblrRequest) JsonParse(content []byte) map[string]interface{} {
	data := map[string]interface{}{}
	err := json.Unmarshal(content, &data)
	if err != nil {
		fmt.Println(err)
	}
	ok_statuses := []int{200, 201, 301}
	status := data["meta"].(map[string]interface{})["status"]
	for _, ok_status := range ok_statuses {
		if status == ok_status {
			return data["response"].(map[string]interface{})
		}
	}
	return data
}

//Generates and makes a multipart request for data files
//url: the url you are making the request to
//params: all parameters needed for the request
//files: a list of files
func (tr *TumblrRequest) PostMultipart(url string, params map[string]string, files []string) map[string]interface{} {

}

//Properly encodes the multipart body of the request
//fields: the parameters used in the request
//files: a list of lists containing information about the files
func (tr *TumblrRequest) EncodeMultipartFormdata(fields map[string]string, files []string) (string, string) {

}
<commit_msg>Fix import statement<commit_after>package gotumblr

import (
		"net/url"
		"net/http"
		"io/ioutil"
		"encoding/json"
		"github.com/kurrik/oauth1a"
)

//Make queries to the Tumblr API through TumblrRequest
type TumblrRequest struct {
	service *oauth1a.Service
	userConfig *oauth1a.UserConfig
	host string
}

//Initializes the TumblrRequest.
//consumerKey is the consumer key of your Tumblr Application
//consumerSecret is the consumer secret of your Tumblr Application
//callbackUrl is the callback URL of your Tumblr Application
//oauthToken is the user specific token, received from the /access_token endpoint
//oauthSecret is the user specific secret, received from the /access_token endpoint
//host is the host that you are tryng to send information to (e.g. http://api.tumblr.com)
func NewTumblrRequest(consumerKey, consumerSecret, oauthToken, oauthSecret, callbackUrl, host string) *TumblrRequest {
	service := &oauth1a.Service{
		RequestURL:   "http://www.tumblr.com/oauth/request_token",
		AuthorizeURL: "http://www.rumblr.com/oauth/authorize",
		AccessURL:    "http://www.tumblr.com/oauth/access_token",
		ClientConfig: &oauth1a.ClientConfig{
			ConsumerKey:    consumerKey,
			ConsumerSecret: consumerSecret,
			CallbackURL:    callbackUrl,
	    },
		Signer: new(oauth1a.HmacSha1Signer),
	}
	userConfig := oauth1a.NewAuthorizedConfig(oauthToken, oauthSecret)
	return &TumblrRequest{service, userConfig, host}
}

//Make a GET request to the API with properly formatted parameters
//url: the url you are making the request to
//params: the parameters needed for the request
func (tr *TumblrRequest) Get(url string, params map[string]string) map[string]interface{} {
	full_url := tr.host + url
	if len(params) != 0 {
		values := url.Values{}
		for key, value := range params {
			values.Set(key, value)
			full_url = full_url + "?" + values.Encode()
		}
	}
	httpRequest, err := http.NewRequest("GET", full_url, nil)
	if err != nil {
		fmt.Println(err)
	}
	tr.service.Sign(httpRequest, tr.userConfig)
	var httpResponse *http.Response
	httpClient := new(http.Client)
	httpResponse, err2 := httpClient.Do(httpRequest)
	if err2 != nil {
		fmt.Println(err2)
	}
	defer httpResponse.Body.Close()
	body, err3 := ioutil.ReadAll(httpResponse.Body)
	if err3 != nil {
		fmt.Println(err3)
	}
	return tr.JsonParse(body)
}

//Makes a POST request to the API, allows for multipart data uploads
//url: the url you are making the request to
//params: all the parameters needed for the request
//files: list of files
func (tr *TumblrRequest) Post(url string, params map[string]string, files []string) map[string]interface{} {

}

//Parse JSON response.
//content: the content returned from the web request to be parsed as JSON
func (tr *TumblrRequest) JsonParse(content []byte) map[string]interface{} {
	data := map[string]interface{}{}
	err := json.Unmarshal(content, &data)
	if err != nil {
		fmt.Println(err)
	}
	ok_statuses := []int{200, 201, 301}
	status := data["meta"].(map[string]interface{})["status"]
	for _, ok_status := range ok_statuses {
		if status == ok_status {
			return data["response"].(map[string]interface{})
		}
	}
	return data
}

//Generates and makes a multipart request for data files
//url: the url you are making the request to
//params: all parameters needed for the request
//files: a list of files
func (tr *TumblrRequest) PostMultipart(url string, params map[string]string, files []string) map[string]interface{} {

}

//Properly encodes the multipart body of the request
//fields: the parameters used in the request
//files: a list of lists containing information about the files
func (tr *TumblrRequest) EncodeMultipartFormdata(fields map[string]string, files []string) (string, string) {

}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"strings"
)

const indexPage = `

<title>Euribor rates</title>

Euribor rates

1 week

2 weeks

1 month

2 months

3 months

6 months

9 months

12 months

`

func renderWebapp(baseURL string) string {
	return strings.Replace(indexPage, "URLPLACEHOLDER", baseURL, -1)
}

func baseURL(r *http.Request) string {
	protocol := "https"
	if r.TLS == nil {
		protocol = "http"
	}
	path := strings.Replace(strings.Replace(r.RequestURI, "/webapp/", "", -1), "/webapp", "", -1)

	return protocol + "://" + r.Host + path
}
<commit_msg>Rename chart load function<commit_after>package main

import (
	"net/http"
	"strings"
)

const indexPage = `

<title>Euribor rates</title>

Euribor rates

1 week

2 weeks

1 month

2 months

3 months

6 months

9 months

12 months

`

func renderWebapp(baseURL string) string {
	return strings.Replace(indexPage, "URLPLACEHOLDER", baseURL, -1)
}

func baseURL(r *http.Request) string {
	protocol := "https"
	if r.TLS == nil {
		protocol = "http"
	}
	path := strings.Replace(strings.Replace(r.RequestURI, "/webapp/", "", -1), "/webapp", "", -1)

	return protocol + "://" + r.Host + path
}
<|endoftext|>


<commit_before>package gracedown

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"testing"
	"time"
)

func newLocalListener() net.Listener {
	// this code from net/http/httptest
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
			panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
		}
	}
	return l
}

func TestShutdown_NoKeepAlive(t *testing.T) {
	const expectedBody = "test response body"

	// prepare test server
	chHandlerRequest := make(chan *http.Request)
	chHandlerResponse := make(chan []byte)
	handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		chHandlerRequest <- req
		data := <-chHandlerResponse
		w.Write(data)
	})
	ts := NewWithServer(&http.Server{
		Handler: handler,
	})

	// start server
	l := newLocalListener()
	chServe := make(chan error)
	go func() {
		chServe <- ts.Serve(l)
	}()
	url := "http://" + l.Addr().String()

	client := &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   5 * time.Second,
				KeepAlive: 5 * time.Second,
			}).Dial,
			TLSHandshakeTimeout: 10 * time.Second,
			DisableKeepAlives:   true, // keep-alives are DISABLE!!
			MaxIdleConnsPerHost: 1,
		},
	}

	// first request will be success
	chRequest := make(chan []byte)
	go func() {
		t.Log("request 1st GET")
		resp, err := client.Get(url)
		if err != nil {
			t.Errorf("unexpected error: %v", err)
			chRequest <- nil
			return
		}
		data, _ := ioutil.ReadAll(resp.Body)
		t.Logf("response is '%s'", string(data))
		resp.Body.Close()
		chRequest <- data
	}()

	// close server
	<-chHandlerRequest // wait for recieving the request...
	t.Log("call sever.Close()")
	if ts.Close() != true {
		t.Errorf("first call to Close returned false")
	}
	if ts.Close() != false {
		t.Fatal("second call to Close returned true")
	}

	// second request will be failure, because the server starts shutting down process
	_, err := client.Get(url)
	t.Log("request 2nd GET: %v", err)
	if err == nil {
		t.Errorf("want some error, but not")
	}

	select {
	case <-chServe:
		t.Error("Serve() returned too early")
	default:
	}

	// test the response
	select {
	case <-chRequest:
		t.Error("the response returned too early")
	default:
	}
	chHandlerResponse <- []byte(expectedBody)
	select {
	case data := <-chRequest:
		if string(data) != expectedBody {
			t.Errorf("want %s, got %s", expectedBody, string(data))
		}
	case <-time.After(5 * time.Second):
		t.Errorf("timeout")
	}

	select {
	case err := <-chServe:
		if err != nil {
			t.Errorf("unexpeted error: %v", err)
		}
	case <-time.After(10 * time.Second):
		t.Errorf("timeout")
	}
}
<commit_msg>fix typo<commit_after>package gracedown

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"testing"
	"time"
)

func newLocalListener() net.Listener {
	// this code from net/http/httptest
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
			panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
		}
	}
	return l
}

func TestShutdown_NoKeepAlive(t *testing.T) {
	const expectedBody = "test response body"

	// prepare test server
	chHandlerRequest := make(chan *http.Request)
	chHandlerResponse := make(chan []byte)
	handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		chHandlerRequest <- req
		data := <-chHandlerResponse
		w.Write(data)
	})
	ts := NewWithServer(&http.Server{
		Handler: handler,
	})

	// start server
	l := newLocalListener()
	chServe := make(chan error)
	go func() {
		chServe <- ts.Serve(l)
	}()
	url := "http://" + l.Addr().String()

	client := &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   5 * time.Second,
				KeepAlive: 5 * time.Second,
			}).Dial,
			TLSHandshakeTimeout: 10 * time.Second,
			DisableKeepAlives:   true, // keep-alives are DISABLE!!
			MaxIdleConnsPerHost: 1,
		},
	}

	// first request will be success
	chRequest := make(chan []byte)
	go func() {
		t.Log("request 1st GET")
		resp, err := client.Get(url)
		if err != nil {
			t.Errorf("unexpected error: %v", err)
			chRequest <- nil
			return
		}
		data, _ := ioutil.ReadAll(resp.Body)
		t.Logf("response is '%s'", string(data))
		resp.Body.Close()
		chRequest <- data
	}()

	// close server
	<-chHandlerRequest // wait for recieving the request...
	t.Log("call sever.Close()")
	if ts.Close() != true {
		t.Errorf("first call to Close returned false")
	}
	if ts.Close() != false {
		t.Fatal("second call to Close returned true")
	}

	// second request will be failure, because the server starts shutting down process
	_, err := client.Get(url)
	t.Logf("request 2nd GET: %v", err)
	if err == nil {
		t.Errorf("want some error, but not")
	}

	select {
	case <-chServe:
		t.Error("Serve() returned too early")
	default:
	}

	// test the response
	select {
	case <-chRequest:
		t.Error("the response returned too early")
	default:
	}
	chHandlerResponse <- []byte(expectedBody)
	select {
	case data := <-chRequest:
		if string(data) != expectedBody {
			t.Errorf("want %s, got %s", expectedBody, string(data))
		}
	case <-time.After(5 * time.Second):
		t.Errorf("timeout")
	}

	select {
	case err := <-chServe:
		if err != nil {
			t.Errorf("unexpeted error: %v", err)
		}
	case <-time.After(10 * time.Second):
		t.Errorf("timeout")
	}
}
<|endoftext|>


<commit_before>package goutils

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"

	"github.com/hoveychen/go-utils/flags"
	"github.com/pkg/errors"

	"golang.org/x/net/proxy"
)

var (
	proxyAddr      = flags.String("proxy", "", "Specify proxy address to fetch data")
	proxyType      = flags.String("proxyType", "sock5", "Either sock5 or http for proxy.")
	requestTimeout = flags.Int("requestTimeout", 10, "Timeout in sec when fetching a remote page.")
	downloadClient *http.Client
)

func init() {
	PkgInit(func() {
		httpTransport := &http.Transport{}
		if *proxyAddr != "" {
			switch *proxyType {
			case "http":
				proxyUrl, err := url.Parse(*proxyAddr)
				if err != nil {
					LogFatal("Failed to parse --proxyAddr", err)
				}
				httpTransport.Proxy = http.ProxyURL(proxyUrl)
			case "sock5":
				dialer, err := proxy.SOCKS5("tcp", *proxyAddr, nil, proxy.Direct)
				if err != nil {
					LogFatal("Failed to dial sock5", err)
				}
				httpTransport.Dial = dialer.Dial
			default:
				LogFatal("Unknown proxy type:", *proxyType)
			}
		}

		downloadClient = &http.Client{Transport: httpTransport}
		downloadClient.Timeout = time.Duration(*requestTimeout) * time.Second
		downloadClient.CheckRedirect = modifiedCheckRedirect
	})
}

func modifiedCheckRedirect(req *http.Request, via []*http.Request) error {
	if len(via) >= 15 {
		return errors.New("stopped after 15 redirects")
	}
	return nil
}

func Get(url string) (*http.Response, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, errors.Wrap(err, "New get request")
	}
	resp, err := downloadClient.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "Do get request")
	}
	return resp, nil
}

func PostJson(url string, data interface{}) (*http.Response, error) {
	encodedData, err := json.Marshal(data)
	if err != nil {
		return nil, errors.Wrap(err, "Encode json")
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(encodedData))
	if err != nil {
		return nil, errors.Wrap(err, "New post request")
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := downloadClient.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "Do post request")
	}
	return resp, nil
}

// FetchData is a helper function to load local/remote data in the same function.
// Local: goutils.FetchData("/absolute/path/to/file")
// Remote: goutils.FetchData("https://www.google.com")
// Also, it's integrated with proxy in flags.
// TODO(yuheng): Allow more options, while keeping easy use.
func FetchData(path string) ([]byte, error) {
	url, err := url.Parse(path)
	if err != nil {
		return nil, errors.Wrap(err, "Decode url")
	}

	switch url.Scheme {
	case "http", "https":
		resp, err := Get(path)
		if err != nil {
			return nil, errors.Wrap(err, "Http get")
		}
		defer resp.Body.Close()
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errors.Wrap(err, "Read response")
		}
		if resp.StatusCode != http.StatusOK {
			return nil, errors.New(resp.Status + ":" + string(data))
		}

		return data, nil
	case "":
		data, err := ioutil.ReadFile(url.Path)
		if err != nil {
			return nil, errors.Wrap(err, "Read file")
		}
		return data, nil
	default:
		return nil, errors.New("Unknown scheme:" + url.Scheme)
	}
}

// FetchJson is a wrapper to call FetchData() and parse results from json.
func FetchJson(path string, resp interface{}) error {
	d, err := FetchData(path)
	if err != nil {
		return errors.Wrap(err, "Fetch data")
	}
	if err := json.Unmarshal(d, resp); err != nil {
		return errors.Wrap(err, "Decode json")
	}
	return nil
}

// FetchXml is a wrapper to call FetchData() and parse results from xml.
func FetchXml(path string, resp interface{}) error {
	d, err := FetchData(path)
	if err != nil {
		return errors.Wrap(err, "Fetch data")
	}
	if err := xml.Unmarshal(d, resp); err != nil {
		return errors.Wrap(err, "Decode xml")
	}
	return nil
}
<commit_msg>[Request] Add old-school post with form data. (Originally only restful json format)<commit_after>// This is a wrapper of standard http package, exposing out-of-the-box flags like proxy, timeout, json handling.
package goutils

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"

	"github.com/hoveychen/go-utils/flags"
	"github.com/pkg/errors"

	"golang.org/x/net/proxy"
)

var (
	proxyAddr      = flags.String("proxy", "", "Specify proxy address to fetch data")
	proxyType      = flags.String("proxyType", "sock5", "Either sock5 or http for proxy.")
	requestTimeout = flags.Int("requestTimeout", 10, "Timeout in sec when fetching a remote page.")
	downloadClient *http.Client
)

func init() {
	PkgInit(func() {
		httpTransport := &http.Transport{}
		if *proxyAddr != "" {
			switch *proxyType {
			case "http":
				proxyUrl, err := url.Parse(*proxyAddr)
				if err != nil {
					LogFatal("Failed to parse --proxyAddr", err)
				}
				httpTransport.Proxy = http.ProxyURL(proxyUrl)
			case "sock5":
				dialer, err := proxy.SOCKS5("tcp", *proxyAddr, nil, proxy.Direct)
				if err != nil {
					LogFatal("Failed to dial sock5", err)
				}
				httpTransport.Dial = dialer.Dial
			default:
				LogFatal("Unknown proxy type:", *proxyType)
			}
		}

		downloadClient = &http.Client{Transport: httpTransport}
		downloadClient.Timeout = time.Duration(*requestTimeout) * time.Second
		downloadClient.CheckRedirect = modifiedCheckRedirect
	})
}

func modifiedCheckRedirect(req *http.Request, via []*http.Request) error {
	if len(via) >= 15 {
		return errors.New("stopped after 15 redirects")
	}
	return nil
}

func Get(url string) (*http.Response, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, errors.Wrap(err, "New get request")
	}
	resp, err := downloadClient.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "Do get request")
	}
	return resp, nil
}

func PostForm(uri string, data map[string]string) (*http.Response, error) {
	values := url.Values{}
	for k, v := range data {
		values.Set(k, v)
	}
	req, err := http.NewRequest("POST", uri, bytes.NewBufferString(values.Encode()))
	if err != nil {
		return nil, errors.Wrap(err, "New post request")
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	resp, err := downloadClient.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "Do post request")
	}
	return resp, nil
}

func PostJson(url string, data interface{}) (*http.Response, error) {
	encodedData, err := json.Marshal(data)
	if err != nil {
		return nil, errors.Wrap(err, "Encode json")
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(encodedData))
	if err != nil {
		return nil, errors.Wrap(err, "New post request")
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := downloadClient.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "Do post request")
	}
	return resp, nil
}

// FetchData is a helper function to load local/remote data in the same function.
// Local: goutils.FetchData("/absolute/path/to/file")
// Remote: goutils.FetchData("https://www.google.com")
// Also, it's integrated with proxy in flags.
// TODO(yuheng): Allow more options, while keeping easy use.
func FetchData(path string) ([]byte, error) {
	url, err := url.Parse(path)
	if err != nil {
		return nil, errors.Wrap(err, "Decode url")
	}

	switch url.Scheme {
	case "http", "https":
		resp, err := Get(path)
		if err != nil {
			return nil, errors.Wrap(err, "Http get")
		}
		defer resp.Body.Close()
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errors.Wrap(err, "Read response")
		}
		if resp.StatusCode != http.StatusOK {
			return nil, errors.New(resp.Status + ":" + string(data))
		}

		return data, nil
	case "":
		data, err := ioutil.ReadFile(url.Path)
		if err != nil {
			return nil, errors.Wrap(err, "Read file")
		}
		return data, nil
	default:
		return nil, errors.New("Unknown scheme:" + url.Scheme)
	}
}

// FetchJson is a wrapper to call FetchData() and parse results from json.
func FetchJson(path string, resp interface{}) error {
	d, err := FetchData(path)
	if err != nil {
		return errors.Wrap(err, "Fetch data")
	}
	if err := json.Unmarshal(d, resp); err != nil {
		return errors.Wrap(err, "Decode json")
	}
	return nil
}

// FetchXml is a wrapper to call FetchData() and parse results from xml.
func FetchXml(path string, resp interface{}) error {
	d, err := FetchData(path)
	if err != nil {
		return errors.Wrap(err, "Fetch data")
	}
	if err := xml.Unmarshal(d, resp); err != nil {
		return errors.Wrap(err, "Decode xml")
	}
	return nil
}
<|endoftext|>


<commit_before>package sorter

import (
	"fmt"
	"testing"
)

// TestInsertionSortManual
func TestInsertionSortManual(t *testing.T) {
	arrRandom := []int{7, 2, 5, 4, 6, 9}
	resultArr := []int{2, 4, 5, 6, 7, 9}
	arr := InsertionSort(arrRandom)
	exp := resultArr
	equals(t, exp, arr)
}

func TestInsertionSort(t *testing.T) {
	generatedArr, err := GenerateArray(8)
	if err != nil {
		t.Fatal(err.Error())
	}

	arr := InsertionSort(generatedArr)
	b, err := IsSorted(arr)
	if err != nil {
		t.Fatal(err.Error())
	}

	if !b {
		fmt.Println("Array is not sorted")
		return
	}
}

func TestRecursiveInsertionSort(t *testing.T) {
	generatedArr, err := GenerateArray(8)
	if err != nil {
		t.Fatal(err.Error())
	}

	arr := RecursiveInsertionSort(generatedArr)
	b, err := IsSorted(arr)
	if err != nil {
		t.Fatal(err.Error())
	}

	if !b {
		fmt.Println("Array is not sorted")
		return
	}
}
<commit_msg>tests: commended insertion sort tests<commit_after>package sorter

import (
	"fmt"
	"testing"
)

// TestInsertionSortManual
func TestInsertionSortManual(t *testing.T) {
	arrRandom := []int{7, 2, 5, 4, 6, 9}
	resultArr := []int{2, 4, 5, 6, 7, 9}
	arr := InsertionSort(arrRandom)
	exp := resultArr
	equals(t, exp, arr)
}

// TestInsertionSort sorts the generated array with insertion sort algorithm
func TestInsertionSort(t *testing.T) {
	generatedArr, err := GenerateArray(8)
	if err != nil {
		t.Fatal(err.Error())
	}

	arr := InsertionSort(generatedArr)
	b, err := IsSorted(arr)
	if err != nil {
		t.Fatal(err.Error())
	}

	if !b {
		fmt.Println("Array is not sorted")
		return
	}
}

// TestRecursiveInsertionSort sorts the generated array with insertion sort algorithm recursively
func TestRecursiveInsertionSort(t *testing.T) {
	generatedArr, err := GenerateArray(8)
	if err != nil {
		t.Fatal(err.Error())
	}

	arr := RecursiveInsertionSort(generatedArr)
	b, err := IsSorted(arr)
	if err != nil {
		t.Fatal(err.Error())
	}

	if !b {
		fmt.Println("Array is not sorted")
		return
	}
}
<|endoftext|>


<commit_before>package importer

import (
	"database/sql"
	"fmt"
	"github.com/gen1us2k/ariadna/common"
	"strconv"
)

func RoadsToPg(Roads []JsonWay) {
	pg_db, err := sql.Open("postgres", common.C.PGConnString)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	defer pg_db.Close()

	_, err = pg_db.Query(`DROP TABLE IF EXISTS road;`)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	_, err = pg_db.Query(`DROP TABLE IF EXISTS road_intersection;`)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	_, err = pg_db.Query(`CREATE TABLE road (
			id serial not null primary key,
			node_id bigint not null,
			name varchar(255) null,
			old_name varchar(255) null,
			coords geometry
		);`)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	_, err = pg_db.Query(`create table road_intersection (
			id serial not null primary key,
			node_id bigint not null,
			name varchar(200) null,
			old_name varchar(255) null,
			coords geometry
		);`)

	if err != nil {
		Logger.Fatal(err.Error())
	}
	if err != nil {
		Logger.Fatal(err.Error())
	}

	Logger.Info("Creating tables")
	Logger.Info("Started populating tables with many roads")

	const insQuery = `INSERT INTO road (node_id, name, old_name, coords) values($1, $2, $3, ST_GeomFromText($4));`
	for _, road := range Roads {
		linestring := "LINESTRING("

		for _, point := range road.Nodes {
			linestring += fmt.Sprintf("%s %s,", strconv.FormatFloat(point.Lng(), 'f', 16, 64), strconv.FormatFloat(point.Lat(), 'f', 16, 64))
		}
		linestring = linestring[:len(linestring)-1]
		linestring += ")"
		insert_query, err := pg_db.Prepare(insQuery)

		if err != nil {
			panic(err)
		}
		defer insert_query.Close()

		name := ""
		if road.Tags["name"] != "" {
			name = road.Tags["name"]
		} else {
			name = road.Tags["addr:name"]
		}

		_, err = insert_query.Exec(road.ID, cleanAddress(name), cleanAddress(road.Tags["old_name"]), linestring)
		if err != nil {
			Logger.Fatal(err.Error())
		}
	}
	searchQuery := `
		INSERT INTO road_intersection( coords, name, old_name, node_id)
			(SELECT DISTINCT (ST_DUMP(ST_INTERSECTION(a.coords, b.coords))).geom AS ix,
			concat(a.name, ' ', b.name) as InterName,
			concat(a.old_name, ' ', b.old_name) as InterOldName,
			a.node_id + b.node_id
			FROM road a
			INNER JOIN road b
			ON ST_INTERSECTS(a.coords,b.coords)
			WHERE geometrytype(st_intersection(a.coords,b.coords)) = 'POINT'
		);
	`
	Logger.Info("Started searching intersections")
	_, err = pg_db.Query(searchQuery)

	if err != nil {
		Logger.Fatal(err.Error())
	}

}

func GetRoadIntersectionsFromPG() []JsonNode {
	var Nodes []JsonNode
	pg_db, err := sql.Open("postgres", common.C.PGConnString)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	defer pg_db.Close()
	rows, err := pg_db.Query("SELECT node_id, name, old_name, st_x((st_dump(coords)).geom) as lng, st_y((st_dump(coords)).geom) as lat from road_intersection")

	if err != nil {
		Logger.Fatal(err.Error())
	}
	for rows.Next() {
		var node PGNode
		rows.Scan(&node.ID, &node.Name, &node.OldName, &node.Lng, &node.Lat)
		tags := make(map[string]string)
		tags["name"] = node.Name
		tags["old_name"] = node.OldName
		jNode := JsonNode{node.ID, "node", node.Lat, node.Lng, tags}
		Nodes = append(Nodes, jNode)
	}
	return Nodes
}
<commit_msg>Don't populate index with same names of road intersections<commit_after>package importer

import (
	"database/sql"
	"fmt"
	"github.com/gen1us2k/ariadna/common"
	"strconv"
)

func RoadsToPg(Roads []JsonWay) {
	pg_db, err := sql.Open("postgres", common.C.PGConnString)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	defer pg_db.Close()

	_, err = pg_db.Query(`DROP TABLE IF EXISTS road;`)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	_, err = pg_db.Query(`DROP TABLE IF EXISTS road_intersection;`)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	_, err = pg_db.Query(`CREATE TABLE road (
			id serial not null primary key,
			node_id bigint not null,
			name varchar(255) null,
			old_name varchar(255) null,
			coords geometry
		);`)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	_, err = pg_db.Query(`create table road_intersection (
			id serial not null primary key,
			node_id bigint not null,
			name varchar(200) null,
			old_name varchar(255) null,
			coords geometry
		);`)

	if err != nil {
		Logger.Fatal(err.Error())
	}
	if err != nil {
		Logger.Fatal(err.Error())
	}

	Logger.Info("Creating tables")
	Logger.Info("Started populating tables with many roads")

	const insQuery = `INSERT INTO road (node_id, name, old_name, coords) values($1, $2, $3, ST_GeomFromText($4));`
	for _, road := range Roads {
		linestring := "LINESTRING("

		for _, point := range road.Nodes {
			linestring += fmt.Sprintf("%s %s,", strconv.FormatFloat(point.Lng(), 'f', 16, 64), strconv.FormatFloat(point.Lat(), 'f', 16, 64))
		}
		linestring = linestring[:len(linestring)-1]
		linestring += ")"
		insert_query, err := pg_db.Prepare(insQuery)

		if err != nil {
			panic(err)
		}
		defer insert_query.Close()

		name := ""
		if road.Tags["name"] != "" {
			name = road.Tags["name"]
		} else {
			name = road.Tags["addr:name"]
		}

		_, err = insert_query.Exec(road.ID, cleanAddress(name), cleanAddress(road.Tags["old_name"]), linestring)
		if err != nil {
			Logger.Fatal(err.Error())
		}
	}
	searchQuery := `
		INSERT INTO road_intersection( coords, name, old_name, node_id)
			(SELECT DISTINCT (ST_DUMP(ST_INTERSECTION(a.coords, b.coords))).geom AS ix,
			concat(a.name, ' ', b.name) as InterName,
			concat(a.old_name, ' ', b.old_name) as InterOldName,
			a.node_id + b.node_id
			FROM road a
			INNER JOIN road b
			ON ST_INTERSECTS(a.coords,b.coords)
			WHERE geometrytype(st_intersection(a.coords,b.coords)) = 'POINT'
			AND a.name != b.name
		);
	`
	Logger.Info("Started searching intersections")
	_, err = pg_db.Query(searchQuery)

	if err != nil {
		Logger.Fatal(err.Error())
	}

}

func GetRoadIntersectionsFromPG() []JsonNode {
	var Nodes []JsonNode
	pg_db, err := sql.Open("postgres", common.C.PGConnString)
	if err != nil {
		Logger.Fatal(err.Error())
	}
	defer pg_db.Close()
	rows, err := pg_db.Query("SELECT node_id, name, old_name, st_x((st_dump(coords)).geom) as lng, st_y((st_dump(coords)).geom) as lat from road_intersection")

	if err != nil {
		Logger.Fatal(err.Error())
	}
	for rows.Next() {
		var node PGNode
		rows.Scan(&node.ID, &node.Name, &node.OldName, &node.Lng, &node.Lat)
		tags := make(map[string]string)
		tags["name"] = node.Name
		tags["old_name"] = node.OldName
		jNode := JsonNode{node.ID, "node", node.Lat, node.Lng, tags}
		Nodes = append(Nodes, jNode)
	}
	return Nodes
}
<|endoftext|>


<commit_before>// Copyright © 2015 Alexey Khalyapin - halyapin@gmail.com
//
// This program or package and any associated files are licensed under the
// GNU GENERAL PUBLIC LICENSE Version 2 (the "License"); you may not use these files
// except in compliance with the License. You can get a copy of the License
// at: http://www.gnu.org/licenses/gpl-2.0.html

package reverse

import (
	"errors"
	"fmt"
	"strings"
)

var Urls *urlStore

func init() {
	Urls = &urlStore{store: make(map[string]url)}
}

// Adds url to store
func Add(urlName, urlAddr string, params ...string) string {
	return Urls.MustAdd(urlName, urlAddr, params...)
}

// Adds url with concat group, but returns just urlAddr
func AddGr(urlName, group, urlAddr string, params ...string) string {
	return Urls.MustAddGr(urlName, group, urlAddr, params...)
}

// Reverse url by name
func Rev(urlName string, params ...string) string {
	return Urls.MustReverse(urlName, params...)
}

// Gets raw url by name
func Get(urlName string) string {
	return Urls.Get(urlName)
}

type url struct {
	url    string
	params []string
}

type urlStore struct {
	store map[string]url
}

// Adds a Url to the Store
func (us *urlStore) Add(urlName, urlAddr string, params ...string) (string, error) {
	return us.AddGr(urlName, "", urlAddr, params...)
}

// Adds a Url and panics if error
func (us urlStore) MustAdd(urlName, urlAddr string, params ...string) string {
	addr, err := us.Add(urlName, urlAddr, params...)
	if err != nil {
		panic(err)
	}
	return addr
}

// Adds with group refix
func (us *urlStore) AddGr(urlName, group, urlAddr string, params ...string) (string, error) {
	if _, ok := us.store[urlName]; ok {
		return "", errors.New("Url already exists. Try to use .Get() method.")
	}

	tmpUrl := url{group + urlAddr, params}
	us.store[urlName] = tmpUrl
	return urlAddr, nil
}

// Adds a Url with group prefix
func (us urlStore) MustAddGr(urlName, group, urlAddr string, params ...string) string {
	addr, err := us.AddGr(urlName, group, urlAddr, params...)
	if err != nil {
		panic(err)
	}
	return addr
}

// Gets raw url string
func (us urlStore) Get(urlName string) string {
	return us.store[urlName].url
}

// Gets reversed url
func (us urlStore) Reverse(urlName string, params ...string) (string, error) {
	if len(params) != len(us.store[urlName].params) {
		return "", errors.New("Bad Url Reverse: mismatch params")
	}
	res := us.store[urlName].url
	for i, val := range params {
		res = strings.Replace(res, us.store[urlName].params[i], val, 1)
	}
	return res, nil
}

// Gets reversed url and panics if error
func (us urlStore) MustReverse(urlName string, params ...string) string {
	res, err := us.Reverse(urlName, params...)
	if err != nil {
		panic(err)
	}
	return res
}

func (us urlStore) Rev(urlName string, params ...string) string {
	return us.MustReverse(urlName, params...)
}

func (us urlStore) Sting() string {
	return fmt.Sprint(us.store)
}

// For testing
func (us urlStore) getParam(urlName string, num int) string {
	return us.store[urlName].params[num]
}

<commit_msg>Added GetAllUrls  and GetAllParams funcs<commit_after>// Copyright © 2015 Alexey Khalyapin - halyapin@gmail.com
//
// This program or package and any associated files are licensed under the
// GNU GENERAL PUBLIC LICENSE Version 2 (the "License"); you may not use these files
// except in compliance with the License. You can get a copy of the License
// at: http://www.gnu.org/licenses/gpl-2.0.html

package reverse

import (
	"errors"
	"fmt"
	"strings"
)

var Urls *urlStore

func init() {
	Urls = &urlStore{store: make(map[string]url)}
}

// Adds url to store
func Add(urlName, urlAddr string, params ...string) string {
	return Urls.MustAdd(urlName, urlAddr, params...)
}

// Adds url with concat group, but returns just urlAddr
func AddGr(urlName, group, urlAddr string, params ...string) string {
	return Urls.MustAddGr(urlName, group, urlAddr, params...)
}

// Reverse url by name
func Rev(urlName string, params ...string) string {
	return Urls.MustReverse(urlName, params...)
}

// Gets raw url by name
func Get(urlName string) string {
	return Urls.Get(urlName)
}

// Gets saved all urls
func GetAllUrls() map[string]string {
	out := map[string]string{}
	for key, value := range Urls.store {
		out[key] = value.url
	}
	return out
}

// Gets all params
func GetAllParams() map[string][]string {
	out := map[string][]string{}
	for key, value := range Urls.store {
		out[key] = value.params
	}
	return out
}

type url struct {
	url    string
	params []string
}

type urlStore struct {
	store map[string]url
}

// Adds a Url to the Store
func (us *urlStore) Add(urlName, urlAddr string, params ...string) (string, error) {
	return us.AddGr(urlName, "", urlAddr, params...)
}

// Adds a Url and panics if error
func (us urlStore) MustAdd(urlName, urlAddr string, params ...string) string {
	addr, err := us.Add(urlName, urlAddr, params...)
	if err != nil {
		panic(err)
	}
	return addr
}

// Adds with group refix
func (us *urlStore) AddGr(urlName, group, urlAddr string, params ...string) (string, error) {
	if _, ok := us.store[urlName]; ok {
		return "", errors.New("Url already exists. Try to use .Get() method.")
	}

	tmpUrl := url{group + urlAddr, params}
	us.store[urlName] = tmpUrl
	return urlAddr, nil
}

// Adds a Url with group prefix
func (us urlStore) MustAddGr(urlName, group, urlAddr string, params ...string) string {
	addr, err := us.AddGr(urlName, group, urlAddr, params...)
	if err != nil {
		panic(err)
	}
	return addr
}

// Gets raw url string
func (us urlStore) Get(urlName string) string {
	return us.store[urlName].url
}

// Gets reversed url
func (us urlStore) Reverse(urlName string, params ...string) (string, error) {
	if len(params) != len(us.store[urlName].params) {
		return "", errors.New("Bad Url Reverse: mismatch params")
	}
	res := us.store[urlName].url
	for i, val := range params {
		res = strings.Replace(res, us.store[urlName].params[i], val, 1)
	}
	return res, nil
}

// Gets reversed url and panics if error
func (us urlStore) MustReverse(urlName string, params ...string) string {
	res, err := us.Reverse(urlName, params...)
	if err != nil {
		panic(err)
	}
	return res
}

func (us urlStore) Rev(urlName string, params ...string) string {
	return us.MustReverse(urlName, params...)
}

func (us urlStore) Sting() string {
	return fmt.Sprint(us.store)
}

// For testing
func (us urlStore) getParam(urlName string, num int) string {
	return us.store[urlName].params[num]
}

<|endoftext|>


<commit_before>/*
 * Copyright 2017-2019 the original author or 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 jprofiler

import (
	"fmt"
	"github.com/gocolly/colly"
	"regexp"
	"resources/check"
	"resources/in"
	"resources/internal"
)

const root = "https://www.ej-technologies.com/download/jprofiler/files"

var checkPattern = internal.Pattern{Regexp: regexp.MustCompile("Version: ([\\d]+)\\.([\\d]+)\\.?([\\d]+)?")}

type JProfiler struct {
	Version internal.Version `json:"version"`
}

func (j JProfiler) Check() (check.Result, error) {
	result := check.Result{Since: j.Version}

	c := colly.NewCollector()

	c.OnHTML(".version-meta h5", func(e *colly.HTMLElement) {

		_ = checkPattern.IfMatches(e.Text, func(g []string) error {
			ref := fmt.Sprintf("%s.%s", g[1], g[2])
			if g[3] != "" {
				ref = fmt.Sprintf("%s.%s", ref, g[3])
			}

			result.Add(internal.Version{Ref: ref})
			return nil
		})
	})

	err := c.Visit(root)
	return result, err
}

func (j JProfiler) In(destination string) (in.Result, error) {
	name, err := j.name()
	if err != nil {
		return in.Result{}, err
	}
	uri := j.uri(name)

	sha256, err := in.Artifact{
		Name:        name,
		Version:     j.Version,
		URI:         uri,
		Destination: destination,
	}.Download()
	if err != nil {
		return in.Result{}, err
	}

	return in.Result{
		Version: j.Version,
		Metadata: []in.Metadata{
			{"uri", uri},
			{"sha256", sha256},
		},
	}, nil
}

func (j JProfiler) name() (string, error) {
	s, err := j.Version.AsSemver()
	if err != nil {
		return "", err
	}

	n := fmt.Sprintf("jprofiler_linux_%d_%d", s.Major(), s.Minor())

	if s.Patch() != 0 {
		n = fmt.Sprintf("%s_%d", n, s.Patch())
	}

	return fmt.Sprintf("%s.tar.gz", n), nil
}

func (j JProfiler) uri(name string) string {
	return fmt.Sprintf("https://download-keycdn.ej-technologies.com/jprofiler/%s", name)
}
<commit_msg>JProfiler Download Location<commit_after>/*
 * Copyright 2017-2019 the original author or 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 jprofiler

import (
	"fmt"
	"github.com/gocolly/colly"
	"regexp"
	"resources/check"
	"resources/in"
	"resources/internal"
)

const root = "https://www.ej-technologies.com/download/jprofiler/files"

var checkPattern = internal.Pattern{Regexp: regexp.MustCompile("Version: ([\\d]+)\\.([\\d]+)\\.?([\\d]+)?")}

type JProfiler struct {
	Version internal.Version `json:"version"`
}

func (j JProfiler) Check() (check.Result, error) {
	result := check.Result{Since: j.Version}

	c := colly.NewCollector()

	c.OnHTML(".version-meta h5", func(e *colly.HTMLElement) {

		_ = checkPattern.IfMatches(e.Text, func(g []string) error {
			ref := fmt.Sprintf("%s.%s", g[1], g[2])
			if g[3] != "" {
				ref = fmt.Sprintf("%s.%s", ref, g[3])
			}

			result.Add(internal.Version{Ref: ref})
			return nil
		})
	})

	err := c.Visit(root)
	return result, err
}

func (j JProfiler) In(destination string) (in.Result, error) {
	name, err := j.name()
	if err != nil {
		return in.Result{}, err
	}
	uri := j.uri(name)

	sha256, err := in.Artifact{
		Name:        name,
		Version:     j.Version,
		URI:         uri,
		Destination: destination,
	}.Download()
	if err != nil {
		return in.Result{}, err
	}

	return in.Result{
		Version: j.Version,
		Metadata: []in.Metadata{
			{"uri", uri},
			{"sha256", sha256},
		},
	}, nil
}

func (j JProfiler) name() (string, error) {
	s, err := j.Version.AsSemver()
	if err != nil {
		return "", err
	}

	n := fmt.Sprintf("jprofiler_linux_%d_%d", s.Major(), s.Minor())

	if s.Patch() != 0 {
		n = fmt.Sprintf("%s_%d", n, s.Patch())
	}

	return fmt.Sprintf("%s.tar.gz", n), nil
}

func (j JProfiler) uri(name string) string {
	return fmt.Sprintf("https://download-gcdn.ej-technologies.com/jprofiler/%s", name)
}
<|endoftext|>