<commit_before>package dry

import (
	"compress/flate"
	"compress/gzip"
	"encoding/json"
	"encoding/xml"
	"io"
	"net/http"
	"strings"
)

type wrappedResponseWriter struct {
	io.Writer
	http.ResponseWriter
}

func (wrapped wrappedResponseWriter) Write(data []byte) (int, error) {
	return wrapped.Writer.Write(data)
}

// HTTPCompressHandlerFunc wraps a http.HandlerFunc so that the response gets
// gzip or deflate compressed if the Accept-Encoding header of the request allows it.
func HTTPCompressHandlerFunc(handlerFunc http.HandlerFunc) http.HandlerFunc {
	return func(response http.ResponseWriter, request *http.Request) {
		accept := request.Header.Get("Accept-Encoding")
		if strings.Contains(accept, "gzip") {
			response.Header().Set("Content-Encoding", "gzip")
			writer := gzip.NewWriter(response)
			defer writer.Close()
			response = wrappedResponseWriter{Writer: writer, ResponseWriter: response}
		} else if strings.Contains(accept, "deflate") {
			response.Header().Set("Content-Encoding", "deflate")
			writer, _ := flate.NewWriter(response, flate.BestCompression)
			defer writer.Close()
			response = wrappedResponseWriter{Writer: writer, ResponseWriter: response}
		}
		handlerFunc(response, request)
	}
}

func HTTPDelete(url string) (statusCode int, statusText string, err error) {
	request, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return 0, "", err
	}
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return 0, "", err
	}
	return response.StatusCode, response.Status, nil
}

// HTTPRespondMarshalJSON marshals response as JSON to responseWriter, sets Content-Type to application/json
// and compresses the response if Content-Encoding from the request allows it.
func HTTPRespondMarshalJSON(response interface{}, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = json.Marshal(response); err == nil {
			responseWriter.Header().Set("Content-Type", "application/json")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondMarshalIndentJSON marshals response as JSON to responseWriter, sets Content-Type to application/json
// and compresses the response if Content-Encoding from the request allows it.
// The JSON will be marshalled indented according to json.MarshalIndent
func HTTPRespondMarshalIndentJSON(response interface{}, prefix, indent string, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = json.MarshalIndent(response, prefix, indent); err == nil {
			responseWriter.Header().Set("Content-Type", "application/json")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondMarshalXML marshals response as XML to responseWriter, sets Content-Type to application/xml
// and compresses the response if Content-Encoding from the request allows it.
func HTTPRespondMarshalXML(response interface{}, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = xml.Marshal(response); err == nil {
			responseWriter.Header().Set("Content-Type", "application/xml")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondMarshalIndentXML marshals response as XML to responseWriter, sets Content-Type to application/xml
// and compresses the response if Content-Encoding from the request allows it.
// The XML will be marshalled indented according to xml.MarshalIndent
func HTTPRespondMarshalIndentXML(response interface{}, prefix, indent string, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = xml.MarshalIndent(response, prefix, indent); err == nil {
			responseWriter.Header().Set("Content-Type", "application/xml")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}
<commit_msg>added HTTPRespondText<commit_after>package dry

import (
	"compress/flate"
	"compress/gzip"
	"encoding/json"
	"encoding/xml"
	"io"
	"net/http"
	"strings"
)

type wrappedResponseWriter struct {
	io.Writer
	http.ResponseWriter
}

func (wrapped wrappedResponseWriter) Write(data []byte) (int, error) {
	return wrapped.Writer.Write(data)
}

// HTTPCompressHandlerFunc wraps a http.HandlerFunc so that the response gets
// gzip or deflate compressed if the Accept-Encoding header of the request allows it.
func HTTPCompressHandlerFunc(handlerFunc http.HandlerFunc) http.HandlerFunc {
	return func(response http.ResponseWriter, request *http.Request) {
		accept := request.Header.Get("Accept-Encoding")
		if strings.Contains(accept, "gzip") {
			response.Header().Set("Content-Encoding", "gzip")
			writer := gzip.NewWriter(response)
			defer writer.Close()
			response = wrappedResponseWriter{Writer: writer, ResponseWriter: response}
		} else if strings.Contains(accept, "deflate") {
			response.Header().Set("Content-Encoding", "deflate")
			writer, _ := flate.NewWriter(response, flate.BestCompression)
			defer writer.Close()
			response = wrappedResponseWriter{Writer: writer, ResponseWriter: response}
		}
		handlerFunc(response, request)
	}
}

func HTTPDelete(url string) (statusCode int, statusText string, err error) {
	request, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return 0, "", err
	}
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return 0, "", err
	}
	return response.StatusCode, response.Status, nil
}

// HTTPRespondMarshalJSON marshals response as JSON to responseWriter, sets Content-Type to application/json
// and compresses the response if Content-Encoding from the request allows it.
func HTTPRespondMarshalJSON(response interface{}, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = json.Marshal(response); err == nil {
			responseWriter.Header().Set("Content-Type", "application/json")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondMarshalIndentJSON marshals response as JSON to responseWriter, sets Content-Type to application/json
// and compresses the response if Content-Encoding from the request allows it.
// The JSON will be marshalled indented according to json.MarshalIndent
func HTTPRespondMarshalIndentJSON(response interface{}, prefix, indent string, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = json.MarshalIndent(response, prefix, indent); err == nil {
			responseWriter.Header().Set("Content-Type", "application/json")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondMarshalXML marshals response as XML to responseWriter, sets Content-Type to application/xml
// and compresses the response if Content-Encoding from the request allows it.
func HTTPRespondMarshalXML(response interface{}, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = xml.Marshal(response); err == nil {
			responseWriter.Header().Set("Content-Type", "application/xml")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondMarshalIndentXML marshals response as XML to responseWriter, sets Content-Type to application/xml
// and compresses the response if Content-Encoding from the request allows it.
// The XML will be marshalled indented according to xml.MarshalIndent
func HTTPRespondMarshalIndentXML(response interface{}, prefix, indent string, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		var data []byte
		if data, err = xml.MarshalIndent(response, prefix, indent); err == nil {
			responseWriter.Header().Set("Content-Type", "application/xml")
			_, err = responseWriter.Write(data)
		}
	})
	handlerFunc(responseWriter, request)
	return err
}

// HTTPRespondText sets Content-Type to text/plain
// and compresses the response if Content-Encoding from the request allows it.
func HTTPRespondText(response string, responseWriter http.ResponseWriter, request *http.Request) (err error) {
	handlerFunc := HTTPCompressHandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
		responseWriter.Header().Set("Content-Type", "text/plain")
		_, err = responseWriter.Write([]byte(response))
	})
	handlerFunc(responseWriter, request)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2013 com 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 com

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"time"
)

type NotFoundError struct {
	Message string
}

func (e NotFoundError) Error() string {
	return e.Message
}

type RemoteError struct {
	Host string
	Err  error
}

func (e *RemoteError) Error() string {
	return e.Err.Error()
}

var UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1541.0 Safari/537.36"

// HttpGet gets the specified resource. ErrNotFound is returned if the
// server responds with status 404.
func HttpGet(client *http.Client, url string, header http.Header) (io.ReadCloser, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", UserAgent)
	for k, vs := range header {
		req.Header[k] = vs
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, &RemoteError{req.URL.Host, err}
	}
	if resp.StatusCode == 200 {
		return resp.Body, nil
	}
	resp.Body.Close()
	if resp.StatusCode == 404 { // 403 can be rate limit error.  || resp.StatusCode == 403 {
		err = NotFoundError{"Resource not found: " + url}
	} else {
		err = &RemoteError{req.URL.Host, fmt.Errorf("get %s -> %d", url, resp.StatusCode)}
	}
	return nil, err
}

// HttpGetToFile gets the specified resource and writes to file.
// ErrNotFound is returned if the server responds with status 404.
func HttpGetToFile(client *http.Client, url string, header http.Header, fileName string) error {
	rc, err := HttpGet(client, url, header)
	if err != nil {
		return err
	}
	defer rc.Close()

	os.MkdirAll(filepath.Dir(fileName), os.ModePerm)
	f, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, rc)
	return err
}

// HttpGetBytes gets the specified resource. ErrNotFound is returned if the server
// responds with status 404.
func HttpGetBytes(client *http.Client, url string, header http.Header) ([]byte, error) {
	rc, err := HttpGet(client, url, header)
	if err != nil {
		return nil, err
	}
	defer rc.Close()
	return ioutil.ReadAll(rc)
}

// HttpGetJSON gets the specified resource and mapping to struct.
// ErrNotFound is returned if the server responds with status 404.
func HttpGetJSON(client *http.Client, url string, v interface{}) error {
	rc, err := HttpGet(client, url, nil)
	if err != nil {
		return err
	}
	defer rc.Close()
	err = json.NewDecoder(rc).Decode(v)
	if _, ok := err.(*json.SyntaxError); ok {
		err = NotFoundError{"JSON syntax error at " + url}
	}
	return err
}

// A RawFile describes a file that can be downloaded.
type RawFile interface {
	Name() string
	RawUrl() string
	Data() []byte
	SetData([]byte)
}

// FetchFiles fetches files specified by the rawURL field in parallel.
func FetchFiles(client *http.Client, files []RawFile, header http.Header) error {
	ch := make(chan error, len(files))
	for i := range files {
		go func(i int) {
			p, err := HttpGetBytes(client, files[i].RawUrl(), nil)
			if err != nil {
				ch <- err
				return
			}
			files[i].SetData(p)
			ch <- nil
		}(i)
	}
	for _ = range files {
		if err := <-ch; err != nil {
			return err
		}
	}
	return nil
}

// FetchFiles uses command `curl` to fetch files specified by the rawURL field in parallel.
func FetchFilesCurl(files []RawFile, curlOptions ...string) error {
	ch := make(chan error, len(files))
	for i := range files {
		go func(i int) {
			stdout, _, err := ExecCmd("curl", append(curlOptions, files[i].RawUrl())...)
			if err != nil {
				ch <- err
				return
			}

			files[i].SetData([]byte(stdout))
			ch <- nil
		}(i)
	}
	for _ = range files {
		if err := <-ch; err != nil {
			return err
		}
	}
	return nil
}

// ==============================
func HttpPost(client *http.Client, url string, body []byte, header http.Header) (io.ReadCloser, error) {
	req, err := http.NewRequest("POST", url, bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", UserAgent)
	for k, vs := range header {
		req.Header[k] = vs
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, &RemoteError{req.URL.Host, err}
	}
	if resp.StatusCode == 200 {
		return resp.Body, nil
	}
	resp.Body.Close()
	if resp.StatusCode == 404 { // 403 can be rate limit error.  || resp.StatusCode == 403 {
		err = NotFoundError{"Resource not found: " + url}
	} else {
		err = &RemoteError{req.URL.Host, fmt.Errorf("get %s -> %d", url, resp.StatusCode)}
	}
	return nil, err
}

func HttpPostBytes(client *http.Client, url string, body []byte, header http.Header) ([]byte, error) {
	rc, err := HttpPost(client, url, body, header)
	if err != nil {
		return nil, err
	}
	p, err := ioutil.ReadAll(rc)
	rc.Close()
	return p, nil
}

func HttpPostJSON(client *http.Client, url string, body []byte, header http.Header) ([]byte, error) {
	if header == nil {
		header = http.Header{}
	}
	header.Add("Content-Type", "application/json")
	p, err := HttpPostBytes(client, url, body, header)
	if err != nil {
		return []byte{}, err
	}
	return p, nil
}

// NewCookie is a helper method that returns a new http.Cookie object.
// Duration is specified in seconds. If the duration is zero, the cookie is permanent.
// This can be used in conjunction with ctx.SetCookie.
func NewCookie(name string, value string, args ...interface{}) *http.Cookie {
	var (
		alen     int = len(args)
		age      int64
		path     string
		domain   string
		secure   bool
		httpOnly bool
	)
	switch alen {
	case 5:
		httpOnly, _ = args[4].(bool)
		fallthrough
	case 4:
		secure, _ = args[3].(bool)
		fallthrough
	case 3:
		domain, _ = args[2].(string)
		fallthrough
	case 2:
		path, _ = args[1].(string)
		fallthrough
	case 1:
		switch args[0].(type) {
		case int:
			age = int64(args[0].(int))
		case int64:
			age = args[0].(int64)
		case time.Duration:
			age = int64(args[0].(time.Duration))
		}
	}
	cookie := &http.Cookie{
		Name:     name,
		Value:    value,
		Path:     path,
		Domain:   domain,
		MaxAge:   0,
		Secure:   secure,
		HttpOnly: httpOnly,
	}
	if age > 0 {
		cookie.Expires = time.Unix(time.Now().Unix()+age, 0)
	} else if age < 0 {
		cookie.Expires = time.Unix(1, 0)
	}
	return cookie
}
<commit_msg>update<commit_after>// Copyright 2013 com 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 com

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"time"
)

type NotFoundError struct {
	Message string
}

func (e NotFoundError) Error() string {
	return e.Message
}

type RemoteError struct {
	Host string
	Err  error
}

func (e *RemoteError) Error() string {
	return e.Err.Error()
}

var UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1541.0 Safari/537.36"

// HttpGet gets the specified resource. ErrNotFound is returned if the
// server responds with status 404.
func HttpGet(client *http.Client, url string, header http.Header) (io.ReadCloser, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", UserAgent)
	for k, vs := range header {
		req.Header[k] = vs
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, &RemoteError{req.URL.Host, err}
	}
	if resp.StatusCode == 200 {
		return resp.Body, nil
	}
	resp.Body.Close()
	if resp.StatusCode == 404 { // 403 can be rate limit error.  || resp.StatusCode == 403 {
		err = NotFoundError{"Resource not found: " + url}
	} else {
		err = &RemoteError{req.URL.Host, fmt.Errorf("get %s -> %d", url, resp.StatusCode)}
	}
	return nil, err
}

// HttpGetToFile gets the specified resource and writes to file.
// ErrNotFound is returned if the server responds with status 404.
func HttpGetToFile(client *http.Client, url string, header http.Header, fileName string) error {
	rc, err := HttpGet(client, url, header)
	if err != nil {
		return err
	}
	defer rc.Close()

	os.MkdirAll(filepath.Dir(fileName), os.ModePerm)
	f, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, rc)
	return err
}

// HttpGetBytes gets the specified resource. ErrNotFound is returned if the server
// responds with status 404.
func HttpGetBytes(client *http.Client, url string, header http.Header) ([]byte, error) {
	rc, err := HttpGet(client, url, header)
	if err != nil {
		return nil, err
	}
	defer rc.Close()
	return ioutil.ReadAll(rc)
}

// HttpGetJSON gets the specified resource and mapping to struct.
// ErrNotFound is returned if the server responds with status 404.
func HttpGetJSON(client *http.Client, url string, v interface{}) error {
	rc, err := HttpGet(client, url, nil)
	if err != nil {
		return err
	}
	defer rc.Close()
	err = json.NewDecoder(rc).Decode(v)
	if _, ok := err.(*json.SyntaxError); ok {
		err = NotFoundError{"JSON syntax error at " + url}
	}
	return err
}

// A RawFile describes a file that can be downloaded.
type RawFile interface {
	Name() string
	RawUrl() string
	Data() []byte
	SetData([]byte)
}

// FetchFiles fetches files specified by the rawURL field in parallel.
func FetchFiles(client *http.Client, files []RawFile, header http.Header) error {
	ch := make(chan error, len(files))
	for i := range files {
		go func(i int) {
			p, err := HttpGetBytes(client, files[i].RawUrl(), nil)
			if err != nil {
				ch <- err
				return
			}
			files[i].SetData(p)
			ch <- nil
		}(i)
	}
	for _ = range files {
		if err := <-ch; err != nil {
			return err
		}
	}
	return nil
}

// FetchFiles uses command `curl` to fetch files specified by the rawURL field in parallel.
func FetchFilesCurl(files []RawFile, curlOptions ...string) error {
	ch := make(chan error, len(files))
	for i := range files {
		go func(i int) {
			stdout, _, err := ExecCmd("curl", append(curlOptions, files[i].RawUrl())...)
			if err != nil {
				ch <- err
				return
			}

			files[i].SetData([]byte(stdout))
			ch <- nil
		}(i)
	}
	for _ = range files {
		if err := <-ch; err != nil {
			return err
		}
	}
	return nil
}

// ==============================
func HttpPost(client *http.Client, url string, body []byte, header http.Header) (io.ReadCloser, error) {
	req, err := http.NewRequest("POST", url, bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", UserAgent)
	for k, vs := range header {
		req.Header[k] = vs
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, &RemoteError{req.URL.Host, err}
	}
	if resp.StatusCode == 200 {
		return resp.Body, nil
	}
	resp.Body.Close()
	if resp.StatusCode == 404 { // 403 can be rate limit error.  || resp.StatusCode == 403 {
		err = NotFoundError{"Resource not found: " + url}
	} else {
		err = &RemoteError{req.URL.Host, fmt.Errorf("get %s -> %d", url, resp.StatusCode)}
	}
	return nil, err
}

func HttpPostBytes(client *http.Client, url string, body []byte, header http.Header) ([]byte, error) {
	rc, err := HttpPost(client, url, body, header)
	if err != nil {
		return nil, err
	}
	p, err := ioutil.ReadAll(rc)
	rc.Close()
	return p, nil
}

func HttpPostJSON(client *http.Client, url string, body []byte, header http.Header) ([]byte, error) {
	if header == nil {
		header = http.Header{}
	}
	header.Add("Content-Type", "application/json")
	p, err := HttpPostBytes(client, url, body, header)
	if err != nil {
		return []byte{}, err
	}
	return p, nil
}

// NewCookie is a helper method that returns a new http.Cookie object.
// Duration is specified in seconds. If the duration is zero, the cookie is permanent.
// This can be used in conjunction with ctx.SetCookie.
func NewCookie(name string, value string, args ...interface{}) *http.Cookie {
	var (
		alen     int = len(args)
		age      int64
		path     string
		domain   string
		secure   bool
		httpOnly bool
	)
	switch alen {
	case 5:
		httpOnly, _ = args[4].(bool)
		fallthrough
	case 4:
		secure, _ = args[3].(bool)
		fallthrough
	case 3:
		domain, _ = args[2].(string)
		fallthrough
	case 2:
		path, _ = args[1].(string)
		fallthrough
	case 1:
		switch args[0].(type) {
		case int:
			age = int64(args[0].(int))
		case int64:
			age = args[0].(int64)
		case time.Duration:
			age = int64(args[0].(time.Duration))
		}
	}
	cookie := &http.Cookie{
		Name:     name,
		Value:    value,
		Path:     path,
		Domain:   domain,
		MaxAge:   0,
		Secure:   secure,
		HttpOnly: httpOnly,
	}
	if age > 0 {
		cookie.Expires = time.Unix(time.Now().Unix()+age, 0)
	} else if age < 0 {
		cookie.Expires = time.Unix(1, 0)
	}
	return cookie
}

func HTTPClientWithTimeout(timeout time.Duration) *http.Client {
	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				conn, err := net.DialTimeout(netw, addr, time.Second*2)
				if err != nil {
					return nil, err
				}
				conn.SetDeadline(time.Now().Add(timeout))
				return conn, nil
			},
			ResponseHeaderTimeout: timeout,
		},
	}
	return client
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net/http"
	"os"
	"strconv"

	"hawx.me/code/ihkh/flickr"
	"hawx.me/code/ihkh/views"
	"hawx.me/code/route"
	"hawx.me/code/serve"
)

var (
	port   = flag.String("port", "8080", "")
	socket = flag.String("socket", "", "")
	userId = flag.String("user-id", "", "")
)

func getCtx(client *flickr.Client, userInfo views.UserInfo, page int) (views.Ctx, error) {
	resp, err := client.PublicPhotos(userInfo.Id, 10, page)
	if err != nil {
		return views.Ctx{}, err
	}

	ctx := views.Ctx{
		Title:    "ihkh : " + userInfo.UserName,
		Photos:   []views.Photo{},
		UserInfo: userInfo,
		Width:    500,
		PrevPage: -1,
		NextPage: -1,
	}

	if resp.Photos.Page > 1 {
		ctx.PrevPage = resp.Photos.Page - 1
		ctx.HasPrevPage = true
	}
	if resp.Photos.Page != resp.Photos.Pages {
		ctx.NextPage = resp.Photos.Page + 1
		ctx.HasNextPage = true
	}

	for _, photo := range resp.Photos.Photo {
		ctx.Photos = append(ctx.Photos, views.Photo{
			Id:     photo.Id,
			Src:    photo.Url,
			Width:  photo.Width,
			Height: photo.Height,
		})
	}

	return ctx, nil
}

func main() {
	flag.Parse()

	client := flickr.New(os.Getenv("FLICKR_KEY"))

	user, err := client.UserInfoForId(*userId)
	if err != nil {
		log.Println(err)
		return
	}

	userInfo := views.UserInfo{
		Id:         *userId,
		PhotosUrl:  user.Person.PhotosUrl,
		ProfileUrl: user.Person.ProfileUrl,
		UserName:   user.Person.Username,
		RealName:   user.Person.Realname,
	}

	route.HandleFunc("/:page", func(w http.ResponseWriter, r *http.Request) {
		page, err := strconv.Atoi(route.Vars(r)["page"])
		if err != nil || page < 1 {
			page = 1
		}

		ctx, err := getCtx(client, userInfo, page)
		if err != nil {
			log.Println(err)
			w.WriteHeader(500)
			return
		}

		views.Photostream(w, ctx)
	})

	serve.Serve(*port, *socket, route.Default)
}
<commit_msg>Take api key on command line instead of ENV<commit_after>package main

import (
	"flag"
	"log"
	"net/http"
	"strconv"

	"hawx.me/code/ihkh/flickr"
	"hawx.me/code/ihkh/views"
	"hawx.me/code/route"
	"hawx.me/code/serve"
)

var (
	port   = flag.String("port", "8080", "")
	socket = flag.String("socket", "", "")
	userId = flag.String("user-id", "", "")
	apiKey = flag.String("api-key", "", "")
)

func getCtx(client *flickr.Client, userInfo views.UserInfo, page int) (views.Ctx, error) {
	resp, err := client.PublicPhotos(userInfo.Id, 10, page)
	if err != nil {
		return views.Ctx{}, err
	}

	ctx := views.Ctx{
		Title:    "ihkh : " + userInfo.UserName,
		Photos:   []views.Photo{},
		UserInfo: userInfo,
		Width:    500,
		PrevPage: -1,
		NextPage: -1,
	}

	if resp.Photos.Page > 1 {
		ctx.PrevPage = resp.Photos.Page - 1
		ctx.HasPrevPage = true
	}
	if resp.Photos.Page != resp.Photos.Pages {
		ctx.NextPage = resp.Photos.Page + 1
		ctx.HasNextPage = true
	}

	for _, photo := range resp.Photos.Photo {
		ctx.Photos = append(ctx.Photos, views.Photo{
			Id:     photo.Id,
			Src:    photo.Url,
			Width:  photo.Width,
			Height: photo.Height,
		})
	}

	return ctx, nil
}

func main() {
	flag.Parse()

	client := flickr.New(*apiKey)

	user, err := client.UserInfoForId(*userId)
	if err != nil {
		log.Println(err)
		return
	}

	userInfo := views.UserInfo{
		Id:         *userId,
		PhotosUrl:  user.Person.PhotosUrl,
		ProfileUrl: user.Person.ProfileUrl,
		UserName:   user.Person.Username,
		RealName:   user.Person.Realname,
	}

	route.HandleFunc("/:page", func(w http.ResponseWriter, r *http.Request) {
		page, err := strconv.Atoi(route.Vars(r)["page"])
		if err != nil || page < 1 {
			page = 1
		}

		ctx, err := getCtx(client, userInfo, page)
		if err != nil {
			log.Println(err)
			w.WriteHeader(500)
			return
		}

		views.Photostream(w, ctx)
	})

	serve.Serve(*port, *socket, route.Default)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	text "github.com/tonnerre/golang-text"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
)

// LoadInfo loads an Info object from a file path
func LoadInfo(p string) (i Info, err error) {
	data, err := ioutil.ReadFile(p)
	if err != nil {
		log.Fatal("Reading file failed: ", p)
	}

	i = Info{ID: asKey(p)}
	yaml.Unmarshal(data, &i)
	return
}

// Info is the main storage for information. All yaml files map to this.
type Info struct {
	ID      string
	Type    string              `yaml:"type"`
	Summary string              `yaml:"summary"`
	Body    string              `yaml:"body"`
	Command Command             `yaml:"command"`
	Hosts   map[string]Category `yaml:"types"`
}

func (i Info) String() string {
	return fmt.Sprintf("I: %s", i.ID)
}

// Execute will figure out the type of the info and execute accordingly
func (i *Info) Execute(r *Repo, c cli.Args) {
	if i.Type == "info" {
		i.PrintBody()
	} else if i.Type == "command" {
		i.Command.Execute(r, c)
	} else if i.Type == "host" {
		i.ExecuteHost(c)
	} else {
		log.Fatal("Unknown type:", i.Type)
	}
}

// PrintBody will pretty format the body of the item
func (i *Info) PrintBody() {
	out := text.Wrap(i.Body, 80)
	fmt.Println(out)
}

// ExecuteHost opens a ssh connection to the specified host
func (i *Info) ExecuteHost(c cli.Args) {
	clen := len(c)
	switch clen {
	case 0:
		// No further arguments - we have selected a host entry but no type.
		// Print the list of hosts.
		PrintHost(i.Hosts)
	case 1, 2:
		t := c[0]
		if cat, ok := i.Hosts[t]; ok {
			if clen == 1 {
				// One argument, go to the primary of that category
				cat.PrimaryHost().Execute("")
			} else {
				// Two arguments, go to specified host
				x, err := strconv.Atoi(c[1])
				if err != nil {
					log.Fatal("Non-integer argument:", c[1])
				}

				host := cat.Hosts[x]
				host.Execute("")
			}

		} else {
			fmt.Println("No such type:", t)
			fmt.Println(
				fmt.Sprintf("Choices are: %s", strings.Join(ListTypes(i.Hosts), ", ")),
			)
			os.Exit(1)
		}
	}
}

// getHosts gets a string representation of all of the hosts in the item
func (i *Info) getHosts() (hosts []string) {
	for _, host := range GetHosts(i.Hosts) {
		hosts = append(hosts, host.FQDN)
	}

	return
}
<commit_msg>Add storing of full path to info items<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	text "github.com/tonnerre/golang-text"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
)

// LoadInfo loads an Info object from a file path
func LoadInfo(p string) (i Info, err error) {
	data, err := ioutil.ReadFile(p)
	if err != nil {
		log.Fatal("Reading file failed: ", p)
	}

	i = Info{ID: asKey(p), path: p}
	yaml.Unmarshal(data, &i)
	return
}

// Info is the main storage for information. All yaml files map to this.
type Info struct {
	ID      string
	Type    string              `yaml:"type"`
	Summary string              `yaml:"summary"`
	Body    string              `yaml:"body"`
	Command Command             `yaml:"command"`
	Hosts   map[string]Category `yaml:"types"`
	path    string
}

func (i Info) String() string {
	return fmt.Sprintf("I: %s", i.ID)
}

// Execute will figure out the type of the info and execute accordingly
func (i *Info) Execute(r *Repo, c cli.Args) {
	if i.Type == "info" {
		i.PrintBody()
	} else if i.Type == "command" {
		i.Command.Execute(r, c)
	} else if i.Type == "host" {
		i.ExecuteHost(c)
	} else {
		log.Fatal("Unknown type:", i.Type)
	}
}

// PrintBody will pretty format the body of the item
func (i *Info) PrintBody() {
	out := text.Wrap(i.Body, 80)
	fmt.Println(out)
}

// ExecuteHost opens a ssh connection to the specified host
func (i *Info) ExecuteHost(c cli.Args) {
	clen := len(c)
	switch clen {
	case 0:
		// No further arguments - we have selected a host entry but no type.
		// Print the list of hosts.
		PrintHost(i.Hosts)
	case 1, 2:
		t := c[0]
		if cat, ok := i.Hosts[t]; ok {
			if clen == 1 {
				// One argument, go to the primary of that category
				cat.PrimaryHost().Execute("")
			} else {
				// Two arguments, go to specified host
				x, err := strconv.Atoi(c[1])
				if err != nil {
					log.Fatal("Non-integer argument:", c[1])
				}

				host := cat.Hosts[x]
				host.Execute("")
			}

		} else {
			fmt.Println("No such type:", t)
			fmt.Println(
				fmt.Sprintf("Choices are: %s", strings.Join(ListTypes(i.Hosts), ", ")),
			)
			os.Exit(1)
		}
	}
}

// getHosts gets a string representation of all of the hosts in the item
func (i *Info) getHosts() (hosts []string) {
	for _, host := range GetHosts(i.Hosts) {
		hosts = append(hosts, host.FQDN)
	}

	return
}
<|endoftext|>


<commit_before>package migo

import (
	"database/sql"
	"fmt"
	"io/ioutil"

	"github.com/pkg/errors"
	"gopkg.in/yaml.v2"
)

func StateInit() error {
	n := StateNew()
	err := n.Update("./database_state.yml")
	if err != nil {
		return errors.Wrap(err, "State file init")
	}
	return nil
}

func DbInit(dbpath, env string) error {
	dbconf, err := NewDb(dbpath, env)
	if err != nil {
		return errors.Wrap(err, "Parse db config")
	}

	dbname := dbconf.DBName
	dbconf.DBName = ""

	sqlconf := NewSql(*dbconf)
	db, err := sql.Open("mysql", sqlconf.DbConf.FormatDSN())
	if err != nil {
		return errors.Wrap(err, "Create mysql connection")
	}
	defer db.Close()

	query := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", dbname)
	fmt.Println(sqlconf.DbConf.FormatDSN, dbname, query)
	if _, err := db.Exec(query); err != nil {
		return errors.Wrap(err, "Create database if not exist")
	}

	return nil
}

func (s *State) Update(path string) error {
	b, err := yaml.Marshal(s)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path, b, 0777)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>delete print debug<commit_after>package migo

import (
	"database/sql"
	"fmt"
	"io/ioutil"

	"github.com/pkg/errors"
	"gopkg.in/yaml.v2"
)

func StateInit() error {
	n := StateNew()
	err := n.Update("./database_state.yml")
	if err != nil {
		return errors.Wrap(err, "State file init")
	}
	return nil
}

func DbInit(dbpath, env string) error {
	dbconf, err := NewDb(dbpath, env)
	if err != nil {
		return errors.Wrap(err, "Parse db config")
	}

	dbname := dbconf.DBName
	dbconf.DBName = ""

	sqlconf := NewSql(*dbconf)
	db, err := sql.Open("mysql", sqlconf.DbConf.FormatDSN())
	if err != nil {
		return errors.Wrap(err, "Create mysql connection")
	}
	defer db.Close()

	query := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", dbname)
	if _, err := db.Exec(query); err != nil {
		return errors.Wrap(err, "Create database if not exist")
	}

	return nil
}

func (s *State) Update(path string) error {
	b, err := yaml.Marshal(s)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path, b, 0777)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "5ef21780ca27d77c6f0ffea6657658020229ffef"
<commit_msg>Tagging Sparta commit<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: Mon Jan 15 22:11:26 PST 2018

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "840ab43181dcea5c32f384d641a62ed0663ee6a6"
<|endoftext|>


<commit_before>package scanner

import (
	"fmt"
	"github.com/Symantec/Dominator/lib/filesystem/scanner"
	"github.com/Symantec/Dominator/lib/filter"
	"github.com/Symantec/Dominator/lib/format"
	"github.com/Symantec/Dominator/lib/fsrateio"
	"github.com/Symantec/Dominator/lib/objectcache"
	"github.com/Symantec/Dominator/lib/rateio"
	"github.com/Symantec/tricorder/go/tricorder"
	"io"
	"log"
	"sync"
	"time"
)

type Configuration struct {
	FsScanContext        *fsrateio.ReaderContext
	NetworkReaderContext *rateio.ReaderContext
	ScanFilter           *filter.Filter
}

func (configuration *Configuration) WriteHtml(writer io.Writer) {
	configuration.writeHtml(writer)
}

func (configuration *Configuration) RegisterMetrics(
	dir *tricorder.DirectorySpec) error {
	return configuration.registerMetrics(dir)
}

type FileSystemHistory struct {
	rwMutex            sync.RWMutex
	fileSystem         *FileSystem
	scanCount          uint64
	generationCount    uint64
	timeOfLastScan     time.Time
	durationOfLastScan time.Duration
	timeOfLastChange   time.Time
}

func (fsh *FileSystemHistory) Update(newFS *FileSystem) {
	fsh.update(newFS)
}

func (fsh *FileSystemHistory) UpdateObjectCacheOnly() error {
	return fsh.updateObjectCacheOnly()
}

func (fsh *FileSystemHistory) FileSystem() *FileSystem {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.fileSystem
}

func (fsh *FileSystemHistory) ScanCount() uint64 {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.scanCount
}

func (fsh *FileSystemHistory) GenerationCount() uint64 {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.generationCount
}

func (fsh FileSystemHistory) String() string {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fmt.Sprintf("GenerationCount=%d\n", fsh.generationCount)
}

func (fsh *FileSystemHistory) WriteHtml(writer io.Writer) {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	fsh.writeHtml(writer)
}

type FileSystem struct {
	configuration     *Configuration
	rootDirectoryName string
	scanner.FileSystem
	cacheDirectoryName string
	objectcache.ObjectCache
}

func ScanFileSystem(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration) (*FileSystem, error) {
	return scanFileSystem(rootDirectoryName, cacheDirectoryName, configuration,
		nil)
}

func (fs *FileSystem) ScanObjectCache() error {
	return fs.scanObjectCache()
}

func (fs *FileSystem) Configuration() *Configuration {
	return fs.configuration
}

func (fs *FileSystem) RootDirectoryName() string {
	return fs.rootDirectoryName
}

func (fs *FileSystem) String() string {
	return fmt.Sprintf("Tree: %d inodes, total file size: %s, number of regular inodes: %d\nObjectCache: %d objects\n",
		len(fs.InodeTable),
		format.FormatBytes(fs.TotalDataBytes),
		fs.NumRegularInodes,
		len(fs.ObjectCache))
}

func (fs *FileSystem) WriteHtml(writer io.Writer) {
	fs.writeHtml(writer)
}

func CompareFileSystems(left, right *FileSystem, logWriter io.Writer) bool {
	return compareFileSystems(left, right, logWriter)
}

func StartScannerDaemon(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration, logger *log.Logger) (
	<-chan *FileSystem, func(disableScanner bool)) {
	return startScannerDaemon(rootDirectoryName, cacheDirectoryName,
		configuration, logger)
}

func StartScanning(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration, logger *log.Logger,
	mainFunc func(<-chan *FileSystem, func(disableScanner bool))) {
	startScanning(rootDirectoryName, cacheDirectoryName, configuration, logger,
		mainFunc)
}
<commit_msg>Add sub/scanner.FileSystemHistory.DurationOfLastScan() method.<commit_after>package scanner

import (
	"fmt"
	"github.com/Symantec/Dominator/lib/filesystem/scanner"
	"github.com/Symantec/Dominator/lib/filter"
	"github.com/Symantec/Dominator/lib/format"
	"github.com/Symantec/Dominator/lib/fsrateio"
	"github.com/Symantec/Dominator/lib/objectcache"
	"github.com/Symantec/Dominator/lib/rateio"
	"github.com/Symantec/tricorder/go/tricorder"
	"io"
	"log"
	"sync"
	"time"
)

type Configuration struct {
	FsScanContext        *fsrateio.ReaderContext
	NetworkReaderContext *rateio.ReaderContext
	ScanFilter           *filter.Filter
}

func (configuration *Configuration) WriteHtml(writer io.Writer) {
	configuration.writeHtml(writer)
}

func (configuration *Configuration) RegisterMetrics(
	dir *tricorder.DirectorySpec) error {
	return configuration.registerMetrics(dir)
}

type FileSystemHistory struct {
	rwMutex            sync.RWMutex
	fileSystem         *FileSystem
	scanCount          uint64
	generationCount    uint64
	timeOfLastScan     time.Time
	durationOfLastScan time.Duration
	timeOfLastChange   time.Time
}

func (fsh *FileSystemHistory) DurationOfLastScan() time.Duration {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.durationOfLastScan
}

func (fsh *FileSystemHistory) FileSystem() *FileSystem {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.fileSystem
}

func (fsh *FileSystemHistory) GenerationCount() uint64 {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.generationCount
}

func (fsh *FileSystemHistory) ScanCount() uint64 {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fsh.scanCount
}

func (fsh FileSystemHistory) String() string {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	return fmt.Sprintf("GenerationCount=%d\n", fsh.generationCount)
}

func (fsh *FileSystemHistory) Update(newFS *FileSystem) {
	fsh.update(newFS)
}

func (fsh *FileSystemHistory) UpdateObjectCacheOnly() error {
	return fsh.updateObjectCacheOnly()
}

func (fsh *FileSystemHistory) WriteHtml(writer io.Writer) {
	fsh.rwMutex.RLock()
	defer fsh.rwMutex.RUnlock()
	fsh.writeHtml(writer)
}

type FileSystem struct {
	configuration     *Configuration
	rootDirectoryName string
	scanner.FileSystem
	cacheDirectoryName string
	objectcache.ObjectCache
}

func ScanFileSystem(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration) (*FileSystem, error) {
	return scanFileSystem(rootDirectoryName, cacheDirectoryName, configuration,
		nil)
}

func (fs *FileSystem) ScanObjectCache() error {
	return fs.scanObjectCache()
}

func (fs *FileSystem) Configuration() *Configuration {
	return fs.configuration
}

func (fs *FileSystem) RootDirectoryName() string {
	return fs.rootDirectoryName
}

func (fs *FileSystem) String() string {
	return fmt.Sprintf("Tree: %d inodes, total file size: %s, number of regular inodes: %d\nObjectCache: %d objects\n",
		len(fs.InodeTable),
		format.FormatBytes(fs.TotalDataBytes),
		fs.NumRegularInodes,
		len(fs.ObjectCache))
}

func (fs *FileSystem) WriteHtml(writer io.Writer) {
	fs.writeHtml(writer)
}

func CompareFileSystems(left, right *FileSystem, logWriter io.Writer) bool {
	return compareFileSystems(left, right, logWriter)
}

func StartScannerDaemon(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration, logger *log.Logger) (
	<-chan *FileSystem, func(disableScanner bool)) {
	return startScannerDaemon(rootDirectoryName, cacheDirectoryName,
		configuration, logger)
}

func StartScanning(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration, logger *log.Logger,
	mainFunc func(<-chan *FileSystem, func(disableScanner bool))) {
	startScanning(rootDirectoryName, cacheDirectoryName, configuration, logger,
		mainFunc)
}
<|endoftext|>


<commit_before>package mustache

import (
    "container/vector"
    "os"
    "path"
    "strings"
    "testing"
)

type Test struct {
    tmpl     string
    context  interface{}
    expected string
}

type Data struct {
    A   bool
    B   string
}

type User struct {
    Name string
    Id   int64
}

type settings struct {
    Allow bool
}

func (u User) Func1() string {
    return u.Name
}

func (u *User) Func2() string {
    return u.Name
}

func (u *User) Func3() (map[string]string, os.Error) {
    return map[string]string{"name": u.Name}, nil
}

func (u *User) Func4() (map[string]string, os.Error) {
    return nil, nil
}

func (u *User) Func5() (*settings, os.Error) {
    return &settings{true}, nil
}

func (u *User) Func6() (*vector.Vector, os.Error) {
    var v vector.Vector
    v.Push(&settings{true})
    return &v, nil
}

func (u User) Truefunc1() bool {
    return true
}

func (u *User) Truefunc2() bool {
    return true
}

func makeVector(n int) *vector.Vector {
    v := new(vector.Vector)
    for i := 0; i < n; i++ {
        v.Push(&User{"Mike", 1})
    }
    return v
}

type Category struct {
    Tag         string
    Description string
}

func (c Category) DisplayName() string {
    return c.Tag + " - " + c.Description
}

var tests = []Test{
    {`hello world`, nil, "hello world"},
    {`hello {{name}}`, map[string]string{"name": "world"}, "hello world"},
    {`{{var}}`, map[string]string{"var": "5 > 2"}, "5 > 2"},
    {`{{{var}}}`, map[string]string{"var": "5 > 2"}, "5 > 2"},
    {`{{a}}{{b}}{{c}}{{d}}`, map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}, "abcd"},
    {`0{{a}}1{{b}}23{{c}}456{{d}}89`, map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}, "0a1b23c456d89"},
    {`hello {{! comment }}world`, map[string]string{}, "hello world"},
    {`{{ a }}{{=<% %>=}}<%b %><%={{ }}=%>{{ c }}`, map[string]string{"a": "a", "b": "b", "c": "c"}, "abc"},
    {`{{ a }}{{= <% %> =}}<%b %><%= {{ }}=%>{{c}}`, map[string]string{"a": "a", "b": "b", "c": "c"}, "abc"},

    //does not exist
    {`{{dne}}`, map[string]string{"name": "world"}, ""},
    {`{{dne}}`, User{"Mike", 1}, ""},
    {`{{dne}}`, &User{"Mike", 1}, ""},
    {`{{#has}}{{/has}}`, &User{"Mike", 1}, ""},

    //section tests
    {`{{#A}}{{B}}{{/A}}`, Data{true, "hello"}, "hello"},
    {`{{#A}}{{{B}}}{{/A}}`, Data{true, "5 > 2"}, "5 > 2"},
    {`{{#A}}{{B}}{{/A}}`, Data{true, "5 > 2"}, "5 > 2"},
    {`{{#A}}{{B}}{{/A}}`, Data{false, "hello"}, ""},
    {`{{a}}{{#b}}{{b}}{{/b}}{{c}}`, map[string]string{"a": "a", "b": "b", "c": "c"}, "abc"},
    {`{{#A}}{{B}}{{/A}}`, struct {
        A []struct {
            B string
        }
    }{[]struct {
        B string
    }{{"a"}, {"b"}, {"c"}}},
        "abc",
    },
    {`{{#A}}{{b}}{{/A}}`, struct{ A []map[string]string }{[]map[string]string{{"b": "a"}, {"b": "b"}, {"b": "c"}}}, "abc"},

    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": []User{{"Mike", 1}}}, "Mike"},

    {`{{#users}}gone{{Name}}{{/users}}`, map[string]interface{}{"users": nil}, ""},
    {`{{#users}}gone{{Name}}{{/users}}`, map[string]interface{}{"users": (*User)(nil)}, ""},
    {`{{#users}}gone{{Name}}{{/users}}`, map[string]interface{}{"users": []User{}}, ""},

    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": vector.Vector([]interface{}{&User{"Mike", 12}})}, "Mike"},
    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": makeVector(1)}, "Mike"},
    {`{{Name}}`, User{"Mike", 1}, "Mike"},
    {`{{Name}}`, &User{"Mike", 1}, "Mike"},
    {"{{#users}}\n{{Name}}\n{{/users}}", map[string]interface{}{"users": makeVector(2)}, "Mike\nMike\n"},
    {"{{#users}}\r\n{{Name}}\r\n{{/users}}", map[string]interface{}{"users": makeVector(2)}, "Mike\r\nMike\r\n"},

    //inverted section tests
    {`{{a}}{{^b}}b{{/b}}{{c}}`, map[string]string{"a": "a", "c": "c"}, "abc"},
    {`{{a}}{{^b}}b{{/b}}{{c}}`, map[string]interface{}{"a": "a", "b": false, "c": "c"}, "abc"},
    {`{{^a}}b{{/a}}`, map[string]interface{}{"a": false}, "b"},
    {`{{^a}}b{{/a}}`, map[string]interface{}{"a": true}, ""},
    {`{{^a}}b{{/a}}`, map[string]interface{}{"a": "nonempty string"}, ""},

    //function tests
    {`{{#users}}{{Func1}}{{/users}}`, map[string]interface{}{"users": []User{{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{Func1}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{Func2}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},

    {`{{#users}}{{#Func3}}{{name}}{{/Func3}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{#Func4}}{{name}}{{/Func4}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, ""},
    {`{{#Truefunc1}}abcd{{/Truefunc1}}`, User{"Mike", 1}, "abcd"},
    {`{{#Truefunc1}}abcd{{/Truefunc1}}`, &User{"Mike", 1}, "abcd"},
    {`{{#Truefunc2}}abcd{{/Truefunc2}}`, &User{"Mike", 1}, "abcd"},
    {`{{#Func5}}{{#Allow}}abcd{{/Allow}}{{/Func5}}`, &User{"Mike", 1}, "abcd"},
    {`{{#user}}{{#Func5}}{{#Allow}}abcd{{/Allow}}{{/Func5}}{{/user}}`, map[string]interface{}{"user": &User{"Mike", 1}}, "abcd"},
    {`{{#user}}{{#Func6}}{{#Allow}}abcd{{/Allow}}{{/Func6}}{{/user}}`, map[string]interface{}{"user": &User{"Mike", 1}}, "abcd"},

    //context chaining
    {`hello {{#section}}{{name}}{{/section}}`, map[string]interface{}{"section": map[string]string{"name": "world"}}, "hello world"},
    {`hello {{#section}}{{name}}{{/section}}`, map[string]interface{}{"name": "bob", "section": map[string]string{"name": "world"}}, "hello world"},
    {`hello {{#bool}}{{#section}}{{name}}{{/section}}{{/bool}}`, map[string]interface{}{"bool": true, "section": map[string]string{"name": "world"}}, "hello world"},
    {`{{#users}}{{canvas}}{{/users}}`, map[string]interface{}{"canvas": "hello", "users": []User{{"Mike", 1}}}, "hello"},
    {`{{#categories}}{{DisplayName}}{{/categories}}`, map[string][]*Category{
        "categories": {&Category{"a", "b"}},
    }, "a - b"},
}

func TestBasic(t *testing.T) {
    for _, test := range tests {
        output := Render(test.tmpl, test.context)
        if output != test.expected {
            t.Fatalf("%q expected %q got %q", test.tmpl, test.expected, output)
        }
    }
}

func TestFile(t *testing.T) {
    filename := path.Join(path.Join(os.Getenv("PWD"), "tests"), "test1.mustache")
    expected := "hello world"
    output := RenderFile(filename, map[string]string{"name": "world"})
    if output != expected {
        t.Fatalf("testfile expected %q got %q", expected, output)
    }
}

func TestPartial(t *testing.T) {
    filename := path.Join(path.Join(os.Getenv("PWD"), "tests"), "test2.mustache")
    expected := "hello world"
    output := RenderFile(filename, map[string]string{"Name": "world"})
    if output != expected {
        t.Fatalf("testpartial expected %q got %q", expected, output)
    }
}
func TestSectionPartial(t *testing.T) {
    filename := path.Join(path.Join(os.Getenv("PWD"), "tests"), "test3.mustache")
    expected := "Mike\nJoe\n"
    context := map[string]interface{}{"users": []User{{"Mike", 1}, {"Joe", 2}}}
    output := RenderFile(filename, context)
    if output != expected {
        t.Fatalf("testSectionPartial expected %q got %q", expected, output)
    }
}

func TestMultiContext(t *testing.T) {
    output := Render(`{{hello}} {{World}}`, map[string]string{"hello": "hello"}, struct{ World string }{"world"})
    output2 := Render(`{{hello}} {{World}}`, struct{ World string }{"world"}, map[string]string{"hello": "hello"})
    if output != "hello world" || output2 != "hello world" {
        t.Fatalf("TestMultiContext expected %q got %q", "hello world", output)
    }
}

var malformed = []Test{
    {`{{#a}}{{}}{{/a}}`, Data{true, "hello"}, "empty tag"},
    {`{{}}`, nil, "empty tag"},
    {`{{}`, nil, "unmatched open tag"},
    {`{{`, nil, "unmatched open tag"},
}

func TestMalformed(t *testing.T) {
    for _, test := range malformed {
        output := Render(test.tmpl, test.context)
        if strings.Index(output, test.expected) == -1 {
            t.Fatalf("%q expected %q in error %q", test.tmpl, test.expected, output)
        }
    }
}

type LayoutTest struct {
    layout   string
    tmpl     string
    context  interface{}
    expected string
}

var layoutTests = []LayoutTest{
    {`Header {{content}} Footer`, `Hello World`, nil, `Header Hello World Footer`},
    {`Header {{content}} Footer`, `Hello {{s}}`, map[string]string{"s": "World"}, `Header Hello World Footer`},
    {`Header {{content}} Footer`, `Hello {{content}}`, map[string]string{"content": "World"}, `Header Hello World Footer`},
    {`Header {{extra}} {{content}} Footer`, `Hello {{content}}`, map[string]string{"content": "World", "extra": "extra"}, `Header extra Hello World Footer`},
    {`Header {{content}} {{content}} Footer`, `Hello {{content}}`, map[string]string{"content": "World"}, `Header Hello World Hello World Footer`},
}

func TestLayout(t *testing.T) {
    for _, test := range layoutTests {
        output := RenderInLayout(test.tmpl, test.layout, test.context)
        if output != test.expected {
            t.Fatalf("%q expected %q got %q", test.tmpl, test.expected, output)
        }
    }
}
<commit_msg>Get rid of container/vector in tests<commit_after>package mustache

import (
    "os"
    "path"
    "strings"
    "testing"
)

type Test struct {
    tmpl     string
    context  interface{}
    expected string
}

type Data struct {
    A   bool
    B   string
}

type User struct {
    Name string
    Id   int64
}

type settings struct {
    Allow bool
}

func (u User) Func1() string {
    return u.Name
}

func (u *User) Func2() string {
    return u.Name
}

func (u *User) Func3() (map[string]string, os.Error) {
    return map[string]string{"name": u.Name}, nil
}

func (u *User) Func4() (map[string]string, os.Error) {
    return nil, nil
}

func (u *User) Func5() (*settings, os.Error) {
    return &settings{true}, nil
}

func (u *User) Func6() ([]interface{}, os.Error) {
    var v []interface{}
    v = append(v, &settings{true})
    return v, nil
}

func (u User) Truefunc1() bool {
    return true
}

func (u *User) Truefunc2() bool {
    return true
}

func makeVector(n int) []interface{} {
    var v []interface{}
    for i := 0; i < n; i++ {
        v = append(v, &User{"Mike", 1})
    }
    return v
}

type Category struct {
    Tag         string
    Description string
}

func (c Category) DisplayName() string {
    return c.Tag + " - " + c.Description
}

var tests = []Test{
    {`hello world`, nil, "hello world"},
    {`hello {{name}}`, map[string]string{"name": "world"}, "hello world"},
    {`{{var}}`, map[string]string{"var": "5 > 2"}, "5 > 2"},
    {`{{{var}}}`, map[string]string{"var": "5 > 2"}, "5 > 2"},
    {`{{a}}{{b}}{{c}}{{d}}`, map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}, "abcd"},
    {`0{{a}}1{{b}}23{{c}}456{{d}}89`, map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}, "0a1b23c456d89"},
    {`hello {{! comment }}world`, map[string]string{}, "hello world"},
    {`{{ a }}{{=<% %>=}}<%b %><%={{ }}=%>{{ c }}`, map[string]string{"a": "a", "b": "b", "c": "c"}, "abc"},
    {`{{ a }}{{= <% %> =}}<%b %><%= {{ }}=%>{{c}}`, map[string]string{"a": "a", "b": "b", "c": "c"}, "abc"},

    //does not exist
    {`{{dne}}`, map[string]string{"name": "world"}, ""},
    {`{{dne}}`, User{"Mike", 1}, ""},
    {`{{dne}}`, &User{"Mike", 1}, ""},
    {`{{#has}}{{/has}}`, &User{"Mike", 1}, ""},

    //section tests
    {`{{#A}}{{B}}{{/A}}`, Data{true, "hello"}, "hello"},
    {`{{#A}}{{{B}}}{{/A}}`, Data{true, "5 > 2"}, "5 > 2"},
    {`{{#A}}{{B}}{{/A}}`, Data{true, "5 > 2"}, "5 > 2"},
    {`{{#A}}{{B}}{{/A}}`, Data{false, "hello"}, ""},
    {`{{a}}{{#b}}{{b}}{{/b}}{{c}}`, map[string]string{"a": "a", "b": "b", "c": "c"}, "abc"},
    {`{{#A}}{{B}}{{/A}}`, struct {
        A []struct {
            B string
        }
    }{[]struct {
        B string
    }{{"a"}, {"b"}, {"c"}}},
        "abc",
    },
    {`{{#A}}{{b}}{{/A}}`, struct{ A []map[string]string }{[]map[string]string{{"b": "a"}, {"b": "b"}, {"b": "c"}}}, "abc"},

    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": []User{{"Mike", 1}}}, "Mike"},

    {`{{#users}}gone{{Name}}{{/users}}`, map[string]interface{}{"users": nil}, ""},
    {`{{#users}}gone{{Name}}{{/users}}`, map[string]interface{}{"users": (*User)(nil)}, ""},
    {`{{#users}}gone{{Name}}{{/users}}`, map[string]interface{}{"users": []User{}}, ""},

    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": []interface{}{&User{"Mike", 12}}}, "Mike"},
    {`{{#users}}{{Name}}{{/users}}`, map[string]interface{}{"users": makeVector(1)}, "Mike"},
    {`{{Name}}`, User{"Mike", 1}, "Mike"},
    {`{{Name}}`, &User{"Mike", 1}, "Mike"},
    {"{{#users}}\n{{Name}}\n{{/users}}", map[string]interface{}{"users": makeVector(2)}, "Mike\nMike\n"},
    {"{{#users}}\r\n{{Name}}\r\n{{/users}}", map[string]interface{}{"users": makeVector(2)}, "Mike\r\nMike\r\n"},

    //inverted section tests
    {`{{a}}{{^b}}b{{/b}}{{c}}`, map[string]string{"a": "a", "c": "c"}, "abc"},
    {`{{a}}{{^b}}b{{/b}}{{c}}`, map[string]interface{}{"a": "a", "b": false, "c": "c"}, "abc"},
    {`{{^a}}b{{/a}}`, map[string]interface{}{"a": false}, "b"},
    {`{{^a}}b{{/a}}`, map[string]interface{}{"a": true}, ""},
    {`{{^a}}b{{/a}}`, map[string]interface{}{"a": "nonempty string"}, ""},

    //function tests
    {`{{#users}}{{Func1}}{{/users}}`, map[string]interface{}{"users": []User{{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{Func1}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{Func2}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},

    {`{{#users}}{{#Func3}}{{name}}{{/Func3}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, "Mike"},
    {`{{#users}}{{#Func4}}{{name}}{{/Func4}}{{/users}}`, map[string]interface{}{"users": []*User{&User{"Mike", 1}}}, ""},
    {`{{#Truefunc1}}abcd{{/Truefunc1}}`, User{"Mike", 1}, "abcd"},
    {`{{#Truefunc1}}abcd{{/Truefunc1}}`, &User{"Mike", 1}, "abcd"},
    {`{{#Truefunc2}}abcd{{/Truefunc2}}`, &User{"Mike", 1}, "abcd"},
    {`{{#Func5}}{{#Allow}}abcd{{/Allow}}{{/Func5}}`, &User{"Mike", 1}, "abcd"},
    {`{{#user}}{{#Func5}}{{#Allow}}abcd{{/Allow}}{{/Func5}}{{/user}}`, map[string]interface{}{"user": &User{"Mike", 1}}, "abcd"},
    {`{{#user}}{{#Func6}}{{#Allow}}abcd{{/Allow}}{{/Func6}}{{/user}}`, map[string]interface{}{"user": &User{"Mike", 1}}, "abcd"},

    //context chaining
    {`hello {{#section}}{{name}}{{/section}}`, map[string]interface{}{"section": map[string]string{"name": "world"}}, "hello world"},
    {`hello {{#section}}{{name}}{{/section}}`, map[string]interface{}{"name": "bob", "section": map[string]string{"name": "world"}}, "hello world"},
    {`hello {{#bool}}{{#section}}{{name}}{{/section}}{{/bool}}`, map[string]interface{}{"bool": true, "section": map[string]string{"name": "world"}}, "hello world"},
    {`{{#users}}{{canvas}}{{/users}}`, map[string]interface{}{"canvas": "hello", "users": []User{{"Mike", 1}}}, "hello"},
    {`{{#categories}}{{DisplayName}}{{/categories}}`, map[string][]*Category{
        "categories": {&Category{"a", "b"}},
    }, "a - b"},
}

func TestBasic(t *testing.T) {
    for _, test := range tests {
        output := Render(test.tmpl, test.context)
        if output != test.expected {
            t.Fatalf("%q expected %q got %q", test.tmpl, test.expected, output)
        }
    }
}

func TestFile(t *testing.T) {
    filename := path.Join(path.Join(os.Getenv("PWD"), "tests"), "test1.mustache")
    expected := "hello world"
    output := RenderFile(filename, map[string]string{"name": "world"})
    if output != expected {
        t.Fatalf("testfile expected %q got %q", expected, output)
    }
}

func TestPartial(t *testing.T) {
    filename := path.Join(path.Join(os.Getenv("PWD"), "tests"), "test2.mustache")
    expected := "hello world"
    output := RenderFile(filename, map[string]string{"Name": "world"})
    if output != expected {
        t.Fatalf("testpartial expected %q got %q", expected, output)
    }
}
func TestSectionPartial(t *testing.T) {
    filename := path.Join(path.Join(os.Getenv("PWD"), "tests"), "test3.mustache")
    expected := "Mike\nJoe\n"
    context := map[string]interface{}{"users": []User{{"Mike", 1}, {"Joe", 2}}}
    output := RenderFile(filename, context)
    if output != expected {
        t.Fatalf("testSectionPartial expected %q got %q", expected, output)
    }
}

func TestMultiContext(t *testing.T) {
    output := Render(`{{hello}} {{World}}`, map[string]string{"hello": "hello"}, struct{ World string }{"world"})
    output2 := Render(`{{hello}} {{World}}`, struct{ World string }{"world"}, map[string]string{"hello": "hello"})
    if output != "hello world" || output2 != "hello world" {
        t.Fatalf("TestMultiContext expected %q got %q", "hello world", output)
    }
}

var malformed = []Test{
    {`{{#a}}{{}}{{/a}}`, Data{true, "hello"}, "empty tag"},
    {`{{}}`, nil, "empty tag"},
    {`{{}`, nil, "unmatched open tag"},
    {`{{`, nil, "unmatched open tag"},
}

func TestMalformed(t *testing.T) {
    for _, test := range malformed {
        output := Render(test.tmpl, test.context)
        if strings.Index(output, test.expected) == -1 {
            t.Fatalf("%q expected %q in error %q", test.tmpl, test.expected, output)
        }
    }
}

type LayoutTest struct {
    layout   string
    tmpl     string
    context  interface{}
    expected string
}

var layoutTests = []LayoutTest{
    {`Header {{content}} Footer`, `Hello World`, nil, `Header Hello World Footer`},
    {`Header {{content}} Footer`, `Hello {{s}}`, map[string]string{"s": "World"}, `Header Hello World Footer`},
    {`Header {{content}} Footer`, `Hello {{content}}`, map[string]string{"content": "World"}, `Header Hello World Footer`},
    {`Header {{extra}} {{content}} Footer`, `Hello {{content}}`, map[string]string{"content": "World", "extra": "extra"}, `Header extra Hello World Footer`},
    {`Header {{content}} {{content}} Footer`, `Hello {{content}}`, map[string]string{"content": "World"}, `Header Hello World Hello World Footer`},
}

func TestLayout(t *testing.T) {
    for _, test := range layoutTests {
        output := RenderInLayout(test.tmpl, test.layout, test.context)
        if output != test.expected {
            t.Fatalf("%q expected %q got %q", test.tmpl, test.expected, output)
        }
    }
}
<|endoftext|>


<commit_before>// chkdomain runs whois lookups against one or more domain names and prints
// those that are available to stdout.
package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

var (
	// Regex for detecting whois response indicating domain is available
	availableRE = regexp.MustCompile(`\b(is not registered|is available|no match for|not found)\b`)
	// Regex for validating a domain, to prevent things like '--foo' from being queried
	domainRE = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9-\.]{0,61}[a-zA-Z0-9])?\.[a-zA-Z]{2,}$`)
	// Time in ms past epoch when program started
	startMS = time.Now().UnixNano() / int64(time.Millisecond)
)

// The result of a whois check for a single domain.
type Result struct {
	domain    string
	output    string
	available bool
	err       error
}

// A currently running job to lookup info for a single domain.
type Job struct {
	domain  string
	results chan<- Result
}

// Run job and send result to 'Job.results'.
func (job Job) Run() {
	result := Result{domain: job.domain}
	if whoisOutput, err := whois(result.domain); err != nil {
		result.err = err
	} else {
		result.output = whoisOutput
		result.available = isDomainAvailable(whoisOutput)
	}
	job.results <- result
}

// Answer whether domain appears to be available based on whois text result.
func isDomainAvailable(whoisText string) bool {
	return availableRE.FindString(strings.ToLower(whoisText)) != ""
}

// Answer whether domain is valid by validating against domainRE regex.
func isDomainValid(domain string) bool {
	return !!domainRE.MatchString(domain)
}

// Get the whois server (including port) for querying a given domain.
func getWhoisServer(domain string) string {
	segments := strings.Split(domain, ".")
	tld := segments[len(segments)-1]
	if len(segments) > 2 {
		tld = segments[len(segments)-2] + "." + tld
	}
	return tld + ".whois-servers.net:43"
}

// Run a whois check for the given domain, returning the non-empty string
// result of the lookup (and nil) on success, or an empty string and error
// on failure.
func whois(domain string) (string, error) {
	if !isDomainValid(domain) {
		return "", errors.New(fmt.Sprintf("invalid domain: %s", domain))
	}
	whoisServer := getWhoisServer(domain)
	if conn, connErr := net.Dial("tcp", whoisServer); connErr != nil {
		msg := fmt.Sprint("error connecting to %v: %v", whoisServer, connErr)
		return "", errors.New(msg)
	} else {
		if _, wrtErr := conn.Write([]byte(domain + "\r\n")); wrtErr != nil {
			return "", wrtErr
		}
		buf := make([]byte, 1024)
		res := []byte{}
		for {
			if numBytes, readErr := conn.Read(buf); numBytes == 0 && readErr != io.EOF {
				return "", readErr
			} else {
				res = append(res, buf[0:numBytes]...)
				if readErr == io.EOF {
					break
				}
			}
		}
		return string(res), nil
	}
}

// Create jobs (without starting them) and send to jobs channel and close it.
func makeJobs(jobs chan<- Job, domains []string, results chan<- Result) {
	for _, domain := range domains {
		jobs <- Job{domain, results}
	}
	close(jobs)
}

// Process results as they are ready, closing 'done' after all expected
// results have been processed (based on numDomains).
func processResults(results chan Result, numDomains int, done chan struct{}, debug bool) {
	processed := 0
	for result := range results {
		processed += 1
		if result.err != nil {
			fmt.Printf("%s\n", result.err)
			continue
		}
		if debug {
			fmt.Printf("[%d]\t", (time.Now().UnixNano()/int64(time.Millisecond))-startMS)
		}
		if result.available {
			if debug {
				fmt.Printf("AVAILABLE\t")
			}
			fmt.Println(result.domain)
		} else {
			if debug {
				fmt.Printf("UNAVAILABLE\t")
				fmt.Println(result.domain)
			}
		}
		if processed >= numDomains {
			close(done)
			return
		}
	}
}

func usage(status int) {
	fmt.Printf("usage: %s [-h] DOMAIN [DOMAIN]*\n\n",
		filepath.Base(os.Args[0]))
	fmt.Printf("If a single '-' param is given, domains will be read ")
	fmt.Printf("from stdin, one domain per line.\n\n")
	fmt.Printf("Domain names that are available will be printed to stdout.\n")
	os.Exit(status)
}

func readLines() ([]string, error) {
	bio := bufio.NewReader(os.Stdin)
	lines := make([]string, 0, 8)
	for {
		line, err := bio.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			} else {
				return lines, err
			}
		}
		lines = append(lines, line[:len(line)-1])
	}
	return lines, nil
}

func main() {
	// At least 1 arg is required, so print usage and fail if none given.
	if len(os.Args) < 2 {
		usage(1)
	}

	debug := flag.Bool("debug", false, "print debug info (all results, with times)")
	help := flag.Bool("help", false, "show usage info")
	flag.Parse()

	if *help {
		usage(0)
	}

	domains := flag.Args()
	numDomains := len(domains)

	// If there's just one arg, check if it's '-' to indicate that
	// domains will be provided one-per-line via stdin, and read them if so.
	if numDomains == 1 && domains[0] == "-" {
		fileDomains, err := readLines()
		if err != nil {
			fmt.Printf("error reading domains from stdin: %s\n", err)
			os.Exit(1)
		}
		domains = fileDomains
	}

	jobs := make(chan Job, numDomains)
	results := make(chan Result, numDomains)
	done := make(chan struct{})

	// Make jobs, which prepares a job for a single domain and will
	// send the result to 'job.results' when done
	go makeJobs(jobs, domains, results)
	// Start all jobs running
	for job := range jobs {
		go job.Run()
	}
	// Process results, waiting on 'done' to be closed after all
	// expected results have been processed.
	go processResults(results, numDomains, done, *debug)
	<-done
}
<commit_msg>numDomains needs to be set again after reading domains from STDIN<commit_after>// chkdomain runs whois lookups against one or more domain names and prints
// those that are available to stdout.
package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

var (
	// Regex for detecting whois response indicating domain is available
	availableRE = regexp.MustCompile(`\b(is not registered|is available|no match for|not found)\b`)
	// Regex for validating a domain, to prevent things like '--foo' from being queried
	domainRE = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9-\.]{0,61}[a-zA-Z0-9])?\.[a-zA-Z]{2,}$`)
	// Time in ms past epoch when program started
	startMS = time.Now().UnixNano() / int64(time.Millisecond)
)

// The result of a whois check for a single domain.
type Result struct {
	domain    string
	output    string
	available bool
	err       error
}

// A currently running job to lookup info for a single domain.
type Job struct {
	domain  string
	results chan<- Result
}

// Run job and send result to 'results' channel.
func (job Job) Run() {
	result := Result{domain: job.domain}
	if whoisOutput, err := whois(result.domain); err != nil {
		result.err = err
	} else {
		result.output = whoisOutput
		result.available = isDomainAvailable(whoisOutput)
	}
	job.results <- result
}

// Answer whether domain appears to be available based on whois text result.
func isDomainAvailable(whoisText string) bool {
	return availableRE.FindString(strings.ToLower(whoisText)) != ""
}

// Answer whether domain is valid by validating against domainRE regex.
func isDomainValid(domain string) bool {
	return !!domainRE.MatchString(domain)
}

// Get the whois server (including port) for querying a given domain.
func getWhoisServer(domain string) string {
	segments := strings.Split(domain, ".")
	tld := segments[len(segments)-1]
	if len(segments) > 2 {
		tld = segments[len(segments)-2] + "." + tld
	}
	return tld + ".whois-servers.net:43"
}

// Run a whois check for the given domain, returning the non-empty string
// result of the lookup (and nil) on success, or an empty string and error
// on failure.
func whois(domain string) (string, error) {
	if !isDomainValid(domain) {
		return "", errors.New(fmt.Sprintf("invalid domain: %s", domain))
	}
	whoisServer := getWhoisServer(domain)
	if conn, connErr := net.Dial("tcp", whoisServer); connErr != nil {
		msg := fmt.Sprint("error connecting to %v: %v", whoisServer, connErr)
		return "", errors.New(msg)
	} else {
		if _, wrtErr := conn.Write([]byte(domain + "\r\n")); wrtErr != nil {
			return "", wrtErr
		}
		buf := make([]byte, 1024)
		res := []byte{}
		for {
			if numBytes, readErr := conn.Read(buf); numBytes == 0 && readErr != io.EOF {
				return "", readErr
			} else {
				res = append(res, buf[0:numBytes]...)
				if readErr == io.EOF {
					break
				}
			}
		}
		return string(res), nil
	}
}

// Create jobs (without starting them) and send to jobs channel and close it.
func makeJobs(jobs chan<- Job, domains []string, results chan<- Result) {
	for _, domain := range domains {
		jobs <- Job{domain, results}
	}
	close(jobs)
}

// Process results as they are ready, closing 'done' after all expected
// results have been processed (based on numDomains).
func processResults(results chan Result, numDomains int, done chan struct{}, debug bool) {
	processed := 0
	for result := range results {
		processed += 1
		if result.err != nil {
			fmt.Printf("%s\n", result.err)
			continue
		}
		if debug {
			fmt.Printf("[%d]\t", (time.Now().UnixNano()/int64(time.Millisecond))-startMS)
		}
		if result.available {
			if debug {
				fmt.Printf("AVAILABLE\t")
			}
			fmt.Println(result.domain)
		} else {
			if debug {
				fmt.Printf("UNAVAILABLE\t")
				fmt.Println(result.domain)
			}
		}
		if processed >= numDomains {
			close(done)
			return
		}
	}
}

func usage(status int) {
	fmt.Printf("usage: %s [-h] DOMAIN [DOMAIN]*\n\n",
		filepath.Base(os.Args[0]))
	fmt.Printf("If a single '-' param is given, domains will be read ")
	fmt.Printf("from stdin, one domain per line.\n\n")
	fmt.Printf("Domain names that are available will be printed to stdout.\n")
	os.Exit(status)
}

func readLines() ([]string, error) {
	bio := bufio.NewReader(os.Stdin)
	lines := make([]string, 0, 8)
	for {
		line, err := bio.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			} else {
				return lines, err
			}
		}
		lines = append(lines, line[:len(line)-1])
	}
	return lines, nil
}

func main() {
	// At least 1 arg is required, so print usage and fail if none given.
	if len(os.Args) < 2 {
		usage(1)
	}

	debug := flag.Bool("debug", false, "print debug info (all results, with times)")
	help := flag.Bool("help", false, "show usage info")
	flag.Parse()

	if *help {
		usage(0)
	}

	domains := flag.Args()
	numDomains := len(domains)

	// If there's just one arg, check if it's '-' to indicate that
	// domains will be provided one-per-line via stdin, and read them if so.
	if numDomains == 1 && domains[0] == "-" {
		fileDomains, err := readLines()
		if err != nil {
			fmt.Printf("error reading domains from stdin: %s\n", err)
			os.Exit(1)
		}
		domains = fileDomains
		numDomains = len(domains)
	}

	jobs := make(chan Job, numDomains)
	results := make(chan Result, numDomains)
	done := make(chan struct{})

	// Make jobs, which prepares a job for a single domain and will
	// send the result to 'job.results' when done
	go makeJobs(jobs, domains, results)
	// Start all jobs running
	for job := range jobs {
		go job.Run()
	}
	// Process results, waiting on 'done' to be closed after all
	// expected results have been processed.
	go processResults(results, numDomains, done, *debug)
	<-done
}
<|endoftext|>


<commit_before>package cleanhttp

import (
	"net"
	"net/http"
	"runtime"
	"time"
)

// DefaultTransport returns a new http.Transport with the same default values
// as http.DefaultTransport
func DefaultTransport() *http.Transport {
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
	}
	SetFinalizer(transport)
	return transport
}

// DefaultClient returns a new http.Client with the same default values as
// http.Client, but with a non-shared Transport
func DefaultClient() *http.Client {
	return &http.Client{
		Transport: DefaultTransport(),
	}
}

func SetFinalizer(transport *http.Transport) {
	runtime.SetFinalizer(&transport, FinalizeTransport)
}

func FinalizeTransport(t **http.Transport) {
	(*t).CloseIdleConnections()
}
<commit_msg>Rename SetFinalizer and move the helper function into a closure<commit_after>package cleanhttp

import (
	"net"
	"net/http"
	"runtime"
	"time"
)

// DefaultTransport returns a new http.Transport with the same default values
// as http.DefaultTransport
func DefaultTransport() *http.Transport {
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
	}
	SetTransportFinalizer(transport)
	return transport
}

// DefaultClient returns a new http.Client with the same default values as
// http.Client, but with a non-shared Transport
func DefaultClient() *http.Client {
	return &http.Client{
		Transport: DefaultTransport(),
	}
}

// SetTransportFinalizer sets a finalizer on the transport to ensure that
// idle connections are closed prior to garbage collection; otherwise
// these may leak
func SetTransportFinalizer(transport *http.Transport) {
	runtime.SetFinalizer(&transport, func(t **http.Transport) {
		(*t).CloseIdleConnections()
	})
}
<|endoftext|>


<commit_before>package config

import (
	"github.com/BurntSushi/toml"
	"strings"
)

const (
	DEFAULT_HOLDTIME                  = 90
	DEFAULT_IDLE_HOLDTIME_AFTER_RESET = 30
)

type neighbor struct {
	attributes map[string]bool
}

func SetDefaultConfigValues(md toml.MetaData, bt *Bgp) {
	neighbors := []neighbor{}

	nidx := 0
	for _, key := range md.Keys() {
		if !strings.HasPrefix(key.String(), "NeighborList") {
			continue
		}
		if key.String() == "NeighborList" {
			neighbors = append(neighbors, neighbor{attributes: make(map[string]bool)})
			nidx++
		} else {
			neighbors[nidx-1].attributes[key.String()] = true
		}
	}
	for i, n := range neighbors {
		if _, ok := n.attributes["NeighborList.Timers.HoldTime"]; !ok {
			bt.NeighborList[i].Timers.HoldTime = float64(DEFAULT_HOLDTIME)
		}
		if _, ok := n.attributes["NeighborList.Timers.KeepaliveInterval"]; !ok {
			bt.NeighborList[i].Timers.KeepaliveInterval = bt.NeighborList[i].Timers.HoldTime / 3
		}

		if _, ok := n.attributes["NeighborList.Timers.IdleHoldTImeAfterReset"]; !ok {
			bt.NeighborList[i].Timers.IdleHoldTimeAfterReset = float64(DEFAULT_IDLE_HOLDTIME_AFTER_RESET)
		}
	}
}
<commit_msg>config: fix attribute name<commit_after>package config

import (
	"github.com/BurntSushi/toml"
	"strings"
)

const (
	DEFAULT_HOLDTIME                  = 90
	DEFAULT_IDLE_HOLDTIME_AFTER_RESET = 30
)

type neighbor struct {
	attributes map[string]bool
}

func SetDefaultConfigValues(md toml.MetaData, bt *Bgp) {
	neighbors := []neighbor{}

	nidx := 0
	for _, key := range md.Keys() {
		if !strings.HasPrefix(key.String(), "NeighborList") {
			continue
		}
		if key.String() == "NeighborList" {
			neighbors = append(neighbors, neighbor{attributes: make(map[string]bool)})
			nidx++
		} else {
			neighbors[nidx-1].attributes[key.String()] = true
		}
	}
	for i, n := range neighbors {
		if _, ok := n.attributes["NeighborList.Timers.HoldTime"]; !ok {
			bt.NeighborList[i].Timers.HoldTime = float64(DEFAULT_HOLDTIME)
		}
		if _, ok := n.attributes["NeighborList.Timers.KeepaliveInterval"]; !ok {
			bt.NeighborList[i].Timers.KeepaliveInterval = bt.NeighborList[i].Timers.HoldTime / 3
		}

		if _, ok := n.attributes["NeighborList.Timers.IdleHoldTimeAfterReset"]; !ok {
			bt.NeighborList[i].Timers.IdleHoldTimeAfterReset = float64(DEFAULT_IDLE_HOLDTIME_AFTER_RESET)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 go-mxnet-predictor Authors. All Rights Reserved.
//
// 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 mxnet

/*
// go preamble
#cgo pkg-config: mxnet
#include <mxnet/c_predict_api.h>
#include <stdlib.h>
*/
import "C"
import (
	"fmt"
	"io/ioutil"
	"unsafe"
)

// NDArray List operator
type NDList struct {
	handle C.NDListHandle // C handle of NDArray List
	size   uint32
}

// NDArray operator
type NDItem struct {
	Key   string    // name of ndarray
	Data  []float32 // actual data of ndarray
	Shape []uint32  // shape
	Ndim  uint32    // the number of dimension in the shape
	Size  uint32    // Shape[0]*Shape[1]....Shape[Ndim-1]
}

// create NDList with a filepath
// go binding for MXNDListCreate
// MXNDListCreate will load mutiple ndarray from the file
func CreateNDListFromFile(filepath string) (*NDList, error) {
	// read file as binary
	b, err := ioutil.ReadFile(filepath)
	if err != nil {
		return nil, err
	}
	if len(b) < 1 {
		// empty
		return nil, fmt.Errorf("empty file")
	}

	var (
		handle C.NDListHandle // go gc, *handle c gc!
		size   uint32         // go gc
	)
	// create ndarray list from raw bytes
	success, err := C.MXNDListCreate((*C.char)(unsafe.Pointer(&b[0])),
		C.int(len(b)),
		&handle,
		(*C.mx_uint)(unsafe.Pointer(&size)),
	)

	if err != nil {
		return nil, err
	}
	if success < 0 {
		return nil, GetLastError()
	}
	return &NDList{handle: handle, size: size}, nil
}

// get an element from ndarray list
// go binding for MXNDListGet
func (s *NDList) Get(index uint32) (*NDItem, error) {
	var (
		key   *C.char     // pointer to name of the item
		data  *C.mx_float // pointer to ndarray data
		shape *C.mx_uint  // pointer to ndarray shape
		ndim  C.mx_uint   // number of dimension in the shape
	)
	success, err := C.MXNDListGet(s.handle,
		C.mx_uint(index),
		&key,
		&data,
		&shape,
		&ndim,
	)
	if err != nil {
		return nil, err
	} else if success < 0 {
		return nil, GetLastError()
	}

	size := uint32(1)
	// c array to go
	goshape := (*[1 << 32]uint32)(unsafe.Pointer(shape))[:ndim:ndim]
	for _, v := range goshape {
		size *= v
	}
	godata := (*[1 << 32]float32)(unsafe.Pointer(data))[:size:size]
	// NDItem go gc
	return &NDItem{
		C.GoString(key),
		godata,
		goshape,
		uint32(ndim),
		size,
	}, nil
}

// free this NDList's C handle
// go binding for MXNDListFree
func (s *NDList) Free() error {
	success, err := C.MXNDListFree(s.handle)
	if err != nil {
		return err
	} else if success < 0 {
		return GetLastError()
	}
	return nil
}
<commit_msg>add CreateNDListFromBytes for predictor<commit_after>// Copyright 2016 go-mxnet-predictor Authors. All Rights Reserved.
//
// 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 mxnet

/*
// go preamble
#cgo pkg-config: mxnet
#include <mxnet/c_predict_api.h>
#include <stdlib.h>
*/
import "C"
import (
	"fmt"
	"io/ioutil"
	"unsafe"
)

// NDArray List operator
type NDList struct {
	handle C.NDListHandle // C handle of NDArray List
	size   uint32
}

// NDArray operator
type NDItem struct {
	Key   string    // name of ndarray
	Data  []float32 // actual data of ndarray
	Shape []uint32  // shape
	Ndim  uint32    // the number of dimension in the shape
	Size  uint32    // Shape[0]*Shape[1]....Shape[Ndim-1]
}

// create NDList from file
// go binding for MXNDListCreate
// MXNDListCreate will load ndarrays from file data
func CreateNDListFromFile(filepath string) (*NDList, error) {
	// read file as binary
	b, err := ioutil.ReadFile(filepath)
	if err != nil {
		return nil, err
	}
	if len(b) < 1 {
		// empty
		return nil, fmt.Errorf("empty file")
	}

	var (
		handle C.NDListHandle // go gc, *handle c gc!
		size   uint32         // go gc
	)
	// create ndarray list from raw bytes
	success, err := C.MXNDListCreate((*C.char)(unsafe.Pointer(&b[0])),
		C.int(len(b)),
		&handle,
		(*C.mx_uint)(unsafe.Pointer(&size)),
	)

	if err != nil {
		return nil, err
	}
	if success < 0 {
		return nil, GetLastError()
	}
	return &NDList{handle: handle, size: size}, nil
}

// create NDList from bytes
// go binding for MXNDListCreate
// MXNDListCreate will load ndarrays from file data
func CreateNDListFromBytes(b []byte) (*NDList, error) {
	if b == nil {
		return nil, fmt.Errorf("input is nil")
	}
	if len(b) < 1 {
		// empty
		return nil, fmt.Errorf("empty input")
	}

	var (
		handle C.NDListHandle // go gc, *handle c gc!
		size   uint32         // go gc
	)
	// create ndarray list from raw bytes
	success, err := C.MXNDListCreate((*C.char)(unsafe.Pointer(&b[0])),
		C.int(len(b)),
		&handle,
		(*C.mx_uint)(unsafe.Pointer(&size)),
	)

	if err != nil {
		return nil, err
	}
	if success < 0 {
		return nil, GetLastError()
	}
	return &NDList{handle: handle, size: size}, nil
}

// get an element from ndarray list
// go binding for MXNDListGet
func (s *NDList) Get(index uint32) (*NDItem, error) {
	var (
		key   *C.char     // pointer to name of the item
		data  *C.mx_float // pointer to ndarray data
		shape *C.mx_uint  // pointer to ndarray shape
		ndim  C.mx_uint   // number of dimension in the shape
	)
	success, err := C.MXNDListGet(s.handle,
		C.mx_uint(index),
		&key,
		&data,
		&shape,
		&ndim,
	)
	if err != nil {
		return nil, err
	} else if success < 0 {
		return nil, GetLastError()
	}

	size := uint32(1)
	// c array to go
	goshape := (*[1 << 32]uint32)(unsafe.Pointer(shape))[:ndim:ndim]
	for _, v := range goshape {
		size *= v
	}
	godata := (*[1 << 32]float32)(unsafe.Pointer(data))[:size:size]
	// NDItem go gc
	return &NDItem{
		C.GoString(key),
		godata,
		goshape,
		uint32(ndim),
		size,
	}, nil
}

// free this NDList's C handle
// go binding for MXNDListFree
func (s *NDList) Free() error {
	success, err := C.MXNDListFree(s.handle)
	if err != nil {
		return err
	} else if success < 0 {
		return GetLastError()
	}
	return nil
}
<|endoftext|>