<commit_before>// main of samples

package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/aliyun/aliyun-oss-go-sdk/sample"
)

// sampleMap contains all samples
var sampleMap = map[string]interface{}{
	"CreateBucketSample":    sample.CreateBucketSample,
	"NewBucketSample":       sample.NewBucketSample,
	"ListBucketsSample":     sample.ListBucketsSample,
	"BucketACLSample":       sample.BucketACLSample,
	"BucketLifecycleSample": sample.BucketLifecycleSample,
	"BucketRefererSample":   sample.BucketRefererSample,
	"BucketLoggingSample":   sample.BucketLoggingSample,
	"BucketCORSSample":      sample.BucketCORSSample,
	"ObjectACLSample":       sample.ObjectACLSample,
	"ObjectMetaSample":      sample.ObjectMetaSample,
	"ListObjectsSample":     sample.ListObjectsSample,
	"DeleteObjectSample":    sample.DeleteObjectSample,
	"AppendObjectSample":    sample.AppendObjectSample,
	"CopyObjectSample":      sample.CopyObjectSample,
	"PutObjectSample":       sample.PutObjectSample,
	"GetObjectSample":       sample.GetObjectSample,
	"CnameSample":           sample.CnameSample,
	"SignURLSample":         sample.SignURLSample,
	"ArchiveSample":         sample.ArchiveSample,
}

func main() {
<<<<<<< HEAD
	sample.CreateBucketSample()
	sample.NewBucketSample()
	sample.ListBucketsSample()
	sample.BucketACLSample()
	sample.BucketLifecycleSample()
	sample.BucketRefererSample()
	sample.BucketLoggingSample()
	sample.BucketCORSSample()

	sample.ObjectACLSample()
	sample.ObjectMetaSample()
	sample.ListObjectsSample()
	sample.DeleteObjectSample()
	sample.AppendObjectSample()
	sample.CopyObjectSample()
	sample.PutObjectSample()
	sample.GetObjectSample()

	sample.CnameSample()
	sample.SignURLSample()

	sample.ArchiveSample()
	sample.ObjectTaggingSample()

	fmt.Println("All samples completed")
=======
	var name string
	flag.StringVar(&name, "name", "", "the sample name")
	flag.Parse()

	if len(name) <= 0 {
		fmt.Println("please enter your sample's name\n like '-name CreateBucketSample'")
		os.Exit(-1)
	} else {
		if sampleMap[name] == nil {
			fmt.Println("the " + name + "is not exist.")
			os.Exit(-1)
		}
		sampleMap[name].(func())()
	}

	// sample.CreateBucketSample()
	// sample.NewBucketSample()
	// sample.ListBucketsSample()
	// sample.BucketACLSample()
	// sample.BucketLifecycleSample()
	// sample.BucketRefererSample()
	// sample.BucketLoggingSample()
	// sample.BucketCORSSample()

	// sample.ObjectACLSample()
	// sample.ObjectMetaSample()
	// sample.ListObjectsSample()
	// sample.DeleteObjectSample()
	// sample.AppendObjectSample()
	// sample.CopyObjectSample()
	// sample.PutObjectSample()
	// sample.GetObjectSample()

	// sample.CnameSample()
	// sample.SignURLSample()

	// sample.ArchiveSample()

	// fmt.Println("All samples completed")
>>>>>>> 86eaf1f... modify the sample main function, let the implementation of a single sample
}
<commit_msg>Modify the sample main of description<commit_after>// main of samples

package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/aliyun/aliyun-oss-go-sdk/sample"
)

// sampleMap contains all samples
var sampleMap = map[string]interface{}{
	"CreateBucketSample":    sample.CreateBucketSample,
	"NewBucketSample":       sample.NewBucketSample,
	"ListBucketsSample":     sample.ListBucketsSample,
	"BucketACLSample":       sample.BucketACLSample,
	"BucketLifecycleSample": sample.BucketLifecycleSample,
	"BucketRefererSample":   sample.BucketRefererSample,
	"BucketLoggingSample":   sample.BucketLoggingSample,
	"BucketCORSSample":      sample.BucketCORSSample,
	"ObjectACLSample":       sample.ObjectACLSample,
	"ObjectMetaSample":      sample.ObjectMetaSample,
	"ListObjectsSample":     sample.ListObjectsSample,
	"DeleteObjectSample":    sample.DeleteObjectSample,
	"AppendObjectSample":    sample.AppendObjectSample,
	"CopyObjectSample":      sample.CopyObjectSample,
	"PutObjectSample":       sample.PutObjectSample,
	"GetObjectSample":       sample.GetObjectSample,
	"CnameSample":           sample.CnameSample,
	"SignURLSample":         sample.SignURLSample,
	"ArchiveSample":         sample.ArchiveSample,
}

func main() {
<<<<<<< HEAD
	sample.CreateBucketSample()
	sample.NewBucketSample()
	sample.ListBucketsSample()
	sample.BucketACLSample()
	sample.BucketLifecycleSample()
	sample.BucketRefererSample()
	sample.BucketLoggingSample()
	sample.BucketCORSSample()

	sample.ObjectACLSample()
	sample.ObjectMetaSample()
	sample.ListObjectsSample()
	sample.DeleteObjectSample()
	sample.AppendObjectSample()
	sample.CopyObjectSample()
	sample.PutObjectSample()
	sample.GetObjectSample()

	sample.CnameSample()
	sample.SignURLSample()

	sample.ArchiveSample()
	sample.ObjectTaggingSample()

	fmt.Println("All samples completed")
=======
	var name string
	flag.StringVar(&name, "name", "", "Waiting for a sample of execution")
	flag.Parse()

	if len(name) <= 0 {
		fmt.Println("please enter your sample's name. like '-name CreateBucketSample'")
		os.Exit(-1)
	} else {
		if sampleMap[name] == nil {
			fmt.Println("the " + name + "is not exist.")
			os.Exit(-1)
		}
		sampleMap[name].(func())()
	}

	// sample.CreateBucketSample()
	// sample.NewBucketSample()
	// sample.ListBucketsSample()
	// sample.BucketACLSample()
	// sample.BucketLifecycleSample()
	// sample.BucketRefererSample()
	// sample.BucketLoggingSample()
	// sample.BucketCORSSample()

	// sample.ObjectACLSample()
	// sample.ObjectMetaSample()
	// sample.ListObjectsSample()
	// sample.DeleteObjectSample()
	// sample.AppendObjectSample()
	// sample.CopyObjectSample()
	// sample.PutObjectSample()
	// sample.GetObjectSample()

	// sample.CnameSample()
	// sample.SignURLSample()

	// sample.ArchiveSample()

	// fmt.Println("All samples completed")
>>>>>>> 86eaf1f... modify the sample main function, let the implementation of a single sample
}
<|endoftext|>


<commit_before>/*
Package sarama is a pure Go client library for dealing with Apache Kafka (versions 0.8 and later). It includes a high-level
API for easily producing and consuming messages, and a low-level API for controlling bytes on the wire when the high-level
API is insufficient. Usage examples for the high-level APIs are provided inline with their full documentation.

To produce messages, use either the AsyncProducer or the SyncProducer. The AsyncProducer accepts messages on a channel
and produces them asynchronously in the background as efficiently as possible; it is preferred in most cases.
The SyncProducer provides a method which will block until Kafka acknowledges the message as produced. This can be
useful but comes with two caveats: it will generally be less efficient, and the actual durability guarantees
depend on the configured value of `Producer.RequiredAcks`. There are configurations where a message acknowledged by the
SyncProducer can still sometimes be lost.

To consume messages, use Consumer or Consumer-Group API.

For lower-level needs, the Broker and Request/Response objects permit precise control over each connection
and message sent on the wire; the Client provides higher-level metadata management that is shared between
the producers and the consumer. The Request/Response objects and properties are mostly undocumented, as they line up
exactly with the protocol fields documented by Kafka at
https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol

Metrics are exposed through https://github.com/rcrowley/go-metrics library in a local registry.

Broker related metrics:

	+----------------------------------------------+------------+---------------------------------------------------------------+
	| Name                                         | Type       | Description                                                   |
	+----------------------------------------------+------------+---------------------------------------------------------------+
	| incoming-byte-rate                           | meter      | Bytes/second read off all brokers                             |
	| incoming-byte-rate-for-broker-<broker-id>    | meter      | Bytes/second read off a given broker                          |
	| outgoing-byte-rate                           | meter      | Bytes/second written off all brokers                          |
	| outgoing-byte-rate-for-broker-<broker-id>    | meter      | Bytes/second written off a given broker                       |
	| request-rate                                 | meter      | Requests/second sent to all brokers                           |
	| request-rate-for-broker-<broker-id>          | meter      | Requests/second sent to a given broker                        |
	| request-size                                 | histogram  | Distribution of the request size in bytes for all brokers     |
	| request-size-for-broker-<broker-id>          | histogram  | Distribution of the request size in bytes for a given broker  |
	| request-latency-in-ms                        | histogram  | Distribution of the request latency in ms for all brokers     |
	| request-latency-in-ms-for-broker-<broker-id> | histogram  | Distribution of the request latency in ms for a given broker  |
	| response-rate                                | meter      | Responses/second received from all brokers                    |
	| response-rate-for-broker-<broker-id>         | meter      | Responses/second received from a given broker                 |
	| response-size                                | histogram  | Distribution of the response size in bytes for all brokers    |
	| response-size-for-broker-<broker-id>         | histogram  | Distribution of the response size in bytes for a given broker |
	+----------------------------------------------+------------+---------------------------------------------------------------+

Note that we do not gather specific metrics for seed brokers but they are part of the "all brokers" metrics.

Producer related metrics:

	+-------------------------------------------+------------+--------------------------------------------------------------------------------------+
	| Name                                      | Type       | Description                                                                          |
	+-------------------------------------------+------------+--------------------------------------------------------------------------------------+
	| batch-size                                | histogram  | Distribution of the number of bytes sent per partition per request for all topics    |
	| batch-size-for-topic-<topic>              | histogram  | Distribution of the number of bytes sent per partition per request for a given topic |
	| record-send-rate                          | meter      | Records/second sent to all topics                                                    |
	| record-send-rate-for-topic-<topic>        | meter      | Records/second sent to a given topic                                                 |
	| records-per-request                       | histogram  | Distribution of the number of records sent per request for all topics                |
	| records-per-request-for-topic-<topic>     | histogram  | Distribution of the number of records sent per request for a given topic             |
	| compression-ratio                         | histogram  | Distribution of the compression ratio times 100 of record batches for all topics     |
	| compression-ratio-for-topic-<topic>       | histogram  | Distribution of the compression ratio times 100 of record batches for a given topic  |
	+-------------------------------------------+------------+--------------------------------------------------------------------------------------+

*/
package sarama

import (
	"io/ioutil"
	"log"
)

// Logger is the instance of a StdLogger interface that Sarama writes connection
// management events to. By default it is set to discard all log messages via ioutil.Discard,
// but you can set it to redirect wherever you want.
var Logger StdLogger = log.New(ioutil.Discard, "[Sarama] ", log.LstdFlags)

// StdLogger is used to log error messages.
type StdLogger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

// PanicHandler is called for recovering from panics spawned internally to the library (and thus
// not recoverable by the caller's goroutine). Defaults to nil, which means panics are not recovered.
var PanicHandler func(interface{})

// MaxRequestSize is the maximum size (in bytes) of any request that Sarama will attempt to send. Trying
// to send a request larger than this will result in an PacketEncodingError. The default of 100 MiB is aligned
// with Kafka's default `socket.request.max.bytes`, which is the largest request the broker will attempt
// to process.
var MaxRequestSize int32 = 100 * 1024 * 1024

// MaxResponseSize is the maximum size (in bytes) of any response that Sarama will attempt to parse. If
// a broker returns a response message larger than this value, Sarama will return a PacketDecodingError to
// protect the client from running out of memory. Please note that brokers do not have any natural limit on
// the size of responses they send. In particular, they can send arbitrarily large fetch responses to consumers
// (see https://issues.apache.org/jira/browse/KAFKA-2063).
var MaxResponseSize int32 = 100 * 1024 * 1024
<commit_msg>go fmt fixes<commit_after>/*
Package sarama is a pure Go client library for dealing with Apache Kafka (versions 0.8 and later). It includes a high-level
API for easily producing and consuming messages, and a low-level API for controlling bytes on the wire when the high-level
API is insufficient. Usage examples for the high-level APIs are provided inline with their full documentation.

To produce messages, use either the AsyncProducer or the SyncProducer. The AsyncProducer accepts messages on a channel
and produces them asynchronously in the background as efficiently as possible; it is preferred in most cases.
The SyncProducer provides a method which will block until Kafka acknowledges the message as produced. This can be
useful but comes with two caveats: it will generally be less efficient, and the actual durability guarantees
depend on the configured value of `Producer.RequiredAcks`. There are configurations where a message acknowledged by the
SyncProducer can still sometimes be lost.

To consume messages, use Consumer or Consumer-Group API.

For lower-level needs, the Broker and Request/Response objects permit precise control over each connection
and message sent on the wire; the Client provides higher-level metadata management that is shared between
the producers and the consumer. The Request/Response objects and properties are mostly undocumented, as they line up
exactly with the protocol fields documented by Kafka at
https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol

Metrics are exposed through https://github.com/rcrowley/go-metrics library in a local registry.

Broker related metrics:

	+----------------------------------------------+------------+---------------------------------------------------------------+
	| Name                                         | Type       | Description                                                   |
	+----------------------------------------------+------------+---------------------------------------------------------------+
	| incoming-byte-rate                           | meter      | Bytes/second read off all brokers                             |
	| incoming-byte-rate-for-broker-<broker-id>    | meter      | Bytes/second read off a given broker                          |
	| outgoing-byte-rate                           | meter      | Bytes/second written off all brokers                          |
	| outgoing-byte-rate-for-broker-<broker-id>    | meter      | Bytes/second written off a given broker                       |
	| request-rate                                 | meter      | Requests/second sent to all brokers                           |
	| request-rate-for-broker-<broker-id>          | meter      | Requests/second sent to a given broker                        |
	| request-size                                 | histogram  | Distribution of the request size in bytes for all brokers     |
	| request-size-for-broker-<broker-id>          | histogram  | Distribution of the request size in bytes for a given broker  |
	| request-latency-in-ms                        | histogram  | Distribution of the request latency in ms for all brokers     |
	| request-latency-in-ms-for-broker-<broker-id> | histogram  | Distribution of the request latency in ms for a given broker  |
	| response-rate                                | meter      | Responses/second received from all brokers                    |
	| response-rate-for-broker-<broker-id>         | meter      | Responses/second received from a given broker                 |
	| response-size                                | histogram  | Distribution of the response size in bytes for all brokers    |
	| response-size-for-broker-<broker-id>         | histogram  | Distribution of the response size in bytes for a given broker |
	+----------------------------------------------+------------+---------------------------------------------------------------+

Note that we do not gather specific metrics for seed brokers but they are part of the "all brokers" metrics.

Producer related metrics:

	+-------------------------------------------+------------+--------------------------------------------------------------------------------------+
	| Name                                      | Type       | Description                                                                          |
	+-------------------------------------------+------------+--------------------------------------------------------------------------------------+
	| batch-size                                | histogram  | Distribution of the number of bytes sent per partition per request for all topics    |
	| batch-size-for-topic-<topic>              | histogram  | Distribution of the number of bytes sent per partition per request for a given topic |
	| record-send-rate                          | meter      | Records/second sent to all topics                                                    |
	| record-send-rate-for-topic-<topic>        | meter      | Records/second sent to a given topic                                                 |
	| records-per-request                       | histogram  | Distribution of the number of records sent per request for all topics                |
	| records-per-request-for-topic-<topic>     | histogram  | Distribution of the number of records sent per request for a given topic             |
	| compression-ratio                         | histogram  | Distribution of the compression ratio times 100 of record batches for all topics     |
	| compression-ratio-for-topic-<topic>       | histogram  | Distribution of the compression ratio times 100 of record batches for a given topic  |
	+-------------------------------------------+------------+--------------------------------------------------------------------------------------+

*/
package sarama

import (
	"io/ioutil"
	"log"
)

// Logger is the instance of a StdLogger interface that Sarama writes connection
// management events to. By default it is set to discard all log messages via ioutil.Discard,
// but you can set it to redirect wherever you want.
var Logger StdLogger = log.New(ioutil.Discard, "[Sarama] ", log.LstdFlags)

// StdLogger is used to log error messages.
type StdLogger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

// PanicHandler is called for recovering from panics spawned internally to the library (and thus
// not recoverable by the caller's goroutine). Defaults to nil, which means panics are not recovered.
var PanicHandler func(interface{})

// MaxRequestSize is the maximum size (in bytes) of any request that Sarama will attempt to send. Trying
// to send a request larger than this will result in an PacketEncodingError. The default of 100 MiB is aligned
// with Kafka's default `socket.request.max.bytes`, which is the largest request the broker will attempt
// to process.
var MaxRequestSize int32 = 100 * 1024 * 1024

// MaxResponseSize is the maximum size (in bytes) of any response that Sarama will attempt to parse. If
// a broker returns a response message larger than this value, Sarama will return a PacketDecodingError to
// protect the client from running out of memory. Please note that brokers do not have any natural limit on
// the size of responses they send. In particular, they can send arbitrarily large fetch responses to consumers
// (see https://issues.apache.org/jira/browse/KAFKA-2063).
var MaxResponseSize int32 = 100 * 1024 * 1024
<|endoftext|>


<commit_before>package hitch

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"runtime"
	"testing"

	"github.com/nbio/st"
)

func TestHome(t *testing.T) {
	s := newTestServer(t)
	_, res := s.request("GET", "/")
	defer res.Body.Close()
	expectHeaders(t, res)
}

func TestEcho(t *testing.T) {
	s := newTestServer(t)
	_, res := s.request("GET", "/api/echo/hip-hop")
	defer res.Body.Close()
	expectHeaders(t, res)
	body, _ := ioutil.ReadAll(res.Body)
	st.Assert(t, string(body), "hip-hop")
}

func TestRouteMiddleware(t *testing.T) {
	s := newTestServer(t)
	_, res := s.request("GET", "/route_middleware")
	defer res.Body.Close()
	expectHeaders(t, res)
	body, _ := ioutil.ReadAll(res.Body)
	st.Assert(t, string(body), "middleware1 -> middleware2 -> Hello, world! -> middleware2 -> middleware1")
}

func expectHeaders(t *testing.T, res *http.Response) {
	st.Expect(t, res.Header.Get("Content-Type"), "text/plain")
	st.Expect(t, res.Header.Get("X-Awesome"), "awesome")
}

// testServer

type testServer struct {
	*httptest.Server
	t *testing.T
}

func (s *testServer) request(method, path string) (*http.Request, *http.Response) {
	req, err := http.NewRequest(method, s.URL+path, nil)
	if err != nil {
		s.t.Fatal(err)
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		s.t.Fatal(err)
	}
	return req, res
}

func newTestServer(t *testing.T) *testServer {
	h := New()
	h.Use(logger, plaintext)
	h.UseHandler(http.HandlerFunc(awesome))
	h.HandleFunc("GET", "/", home)
	api := New()
	api.Get("/api/echo/:phrase", http.HandlerFunc(echo))
	h.Next(api.Handler())
	h.Get("/route_middleware", http.HandlerFunc(home), testMiddleware("middleware1"), testMiddleware("middleware2"))

	s := &testServer{httptest.NewServer(h.Handler()), t}
	runtime.SetFinalizer(s, func(s *testServer) { s.Server.Close() })
	return s
}

func logger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Printf("%s %s\n", req.Method, req.URL.String())
		next.ServeHTTP(w, req)
	})
}

func plaintext(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		next.ServeHTTP(w, req)
	})
}

func awesome(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("X-Awesome", "awesome")
}

func home(w http.ResponseWriter, req *http.Request) {
	fmt.Fprint(w, "Hello, world!")
}

func echo(w http.ResponseWriter, req *http.Request) {
	fmt.Fprint(w, Params(req).ByName("phrase"))
}

func testMiddleware(name string) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			fmt.Fprint(w, name+" -> ")
			next.ServeHTTP(w, req)
			fmt.Fprint(w, " -> "+name)
		})
	}
}
<commit_msg>drop github.com/nbio/st dependency in testing<commit_after>package hitch

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"runtime"
	"testing"
)

func TestHome(t *testing.T) {
	s := newTestServer(t)
	_, res := s.request("GET", "/")
	defer res.Body.Close()
	expectHeaders(t, res)
}

func TestEcho(t *testing.T) {
	s := newTestServer(t)
	_, res := s.request("GET", "/api/echo/hip-hop")
	defer res.Body.Close()
	expectHeaders(t, res)
	body, _ := ioutil.ReadAll(res.Body)

	if g, e := string(body), "hip-hop"; g != e {
		t.Fatalf("should be == \n \thave: %s\n\twant: %s", g, e)
	}
}

func TestRouteMiddleware(t *testing.T) {
	s := newTestServer(t)
	_, res := s.request("GET", "/route_middleware")
	defer res.Body.Close()
	expectHeaders(t, res)
	body, _ := ioutil.ReadAll(res.Body)

	if g, e := string(body), "middleware1 -> middleware2 -> Hello, world! -> middleware2 -> middleware1"; g != e {
		t.Fatalf("should be == \n \thave: %s\n\twant: %s", g, e)
	}
}

func expectHeaders(t *testing.T, res *http.Response) {
	if g, e := res.Header.Get("Content-Type"), "text/plain"; g != e {
		t.Errorf("should be == \n \thave: %s\n\twant: %s", g, e)
	}
	if g, e := res.Header.Get("X-Awesome"), "awesome"; g != e {
		t.Errorf("should be == \n \thave: %s\n\twant: %s", g, e)
	}
}

// testServer
type testServer struct {
	*httptest.Server
	t *testing.T
}

func (s *testServer) request(method, path string) (*http.Request, *http.Response) {
	req, err := http.NewRequest(method, s.URL+path, nil)
	if err != nil {
		s.t.Fatal(err)
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		s.t.Fatal(err)
	}
	return req, res
}

func newTestServer(t *testing.T) *testServer {
	h := New()
	h.Use(logger, plaintext)
	h.UseHandler(http.HandlerFunc(awesome))
	h.HandleFunc("GET", "/", home)
	api := New()
	api.Get("/api/echo/:phrase", http.HandlerFunc(echo))
	h.Next(api.Handler())
	h.Get("/route_middleware", http.HandlerFunc(home), testMiddleware("middleware1"), testMiddleware("middleware2"))

	s := &testServer{httptest.NewServer(h.Handler()), t}
	runtime.SetFinalizer(s, func(s *testServer) { s.Server.Close() })
	return s
}

func logger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Printf("%s %s\n", req.Method, req.URL.String())
		next.ServeHTTP(w, req)
	})
}

func plaintext(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		next.ServeHTTP(w, req)
	})
}

func awesome(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("X-Awesome", "awesome")
}

func home(w http.ResponseWriter, req *http.Request) {
	fmt.Fprint(w, "Hello, world!")
}

func echo(w http.ResponseWriter, req *http.Request) {
	fmt.Fprint(w, Params(req).ByName("phrase"))
}

func testMiddleware(name string) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			fmt.Fprint(w, name+" -> ")
			next.ServeHTTP(w, req)
			fmt.Fprint(w, " -> "+name)
		})
	}
}
<|endoftext|>


<commit_before>package http

import (
	"net/http"

	"github.com/jsok/vending/machine"
)

type itemsListHandler struct {
	machine *machine.Machine
}

func (h *itemsListHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		for _, item := range h.machine.Describe() {
			w.Write([]byte(item.String() + "\n"))
		}
	default:
		http.NotFound(w, r)
	}
}
<commit_msg>Return JSON from GET /api/items<commit_after>package http

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

	"github.com/jsok/vending/machine"
)

type itemsListHandler struct {
	machine *machine.Machine
}

func (h *itemsListHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		b, err := json.Marshal(h.machine.Describe())
		if err != nil {
			http.Error(w, err.Error(), 500)
		}
		w.Write(b)
	default:
		http.NotFound(w, r)
	}
}
<|endoftext|>


<commit_before>package render

import (
	"fmt"

	"github.com/weaveworks/scope/probe/docker"
	"github.com/weaveworks/scope/probe/process"
	"github.com/weaveworks/scope/report"
)

// EndpointRenderer is a Renderer which produces a renderable endpoint graph.
var EndpointRenderer = Map{
	MapFunc:  MapEndpointIdentity,
	Renderer: SelectEndpoint,
}

// ProcessRenderer is a Renderer which produces a renderable process
// graph by merging the endpoint graph and the process topology.
var ProcessRenderer = MakeReduce(
	Map{
		MapFunc:  MapEndpoint2Process,
		Renderer: EndpointRenderer,
	},
	Map{
		MapFunc:  MapProcessIdentity,
		Renderer: SelectProcess,
	},
)

// processWithContainerNameRenderer is a Renderer which produces a process
// graph enriched with container names where appropriate
type processWithContainerNameRenderer struct {
	Renderer
}

func (r processWithContainerNameRenderer) Render(rpt report.Report) RenderableNodes {
	processes := r.Renderer.Render(rpt)
	containers := Map{
		MapFunc:  MapContainerIdentity,
		Renderer: SelectContainer,
	}.Render(rpt)

	for id, p := range processes {
		pid, ok := p.Node.Metadata[process.PID]
		if !ok {
			continue
		}
		containerID, ok := p.Node.Metadata[docker.ContainerID]
		if !ok {
			continue
		}
		container, ok := containers[containerID]
		if !ok {
			continue
		}
		p.LabelMinor = fmt.Sprintf("%s (%s:%s)", report.ExtractHostID(p.Node), container.LabelMajor, pid)
		processes[id] = p
	}

	return processes
}

// ProcessWithContainerNameRenderer is a Renderer which produces a process
// graph enriched with container names where appropriate
var ProcessWithContainerNameRenderer = processWithContainerNameRenderer{ProcessRenderer}

// ProcessNameRenderer is a Renderer which produces a renderable process
// name graph by munging the progess graph.
var ProcessNameRenderer = Map{
	MapFunc: MapCountProcessName,
	Renderer: Map{
		MapFunc:  MapProcess2Name,
		Renderer: ProcessRenderer,
	},
}

// ContainerRenderer is a Renderer which produces a renderable container
// graph by merging the process graph and the container topology.
var ContainerRenderer = MakeReduce(
	Map{
		MapFunc: MapProcess2Container,

		// We only want processes in container _or_ processes with network connections
		// but we need to be careful to ensure we only include each edge once, by only
		// including the ProcessRenderer once.
		Renderer: Filter{
			FilterFunc: func(n RenderableNode) bool {
				_, inContainer := n.Node.Metadata[docker.ContainerID]
				_, isConnected := n.Node.Metadata[IsConnected]
				return inContainer || isConnected
			},
			Renderer: ColorConnected(ProcessRenderer),
		},
	},

	Map{
		MapFunc:  MapContainerIdentity,
		Renderer: SelectContainer,
	},

	// This mapper brings in short lived connections by joining with container IPs.
	// We need to be careful to ensure we only include each edge once.  Edges brought in
	// by the above renders will have a pid, so its enough to filter out any nodes with
	// pids.
	Map{
		MapFunc: MapIP2Container,
		Renderer: FilterUnconnected(
			MakeReduce(
				Map{
					MapFunc:  MapContainer2IP,
					Renderer: SelectContainer,
				},
				Map{
					MapFunc:  MapEndpoint2IP,
					Renderer: SelectEndpoint,
				},
			),
		),
	},
)

type containerWithImageNameRenderer struct {
	Renderer
}

// Render produces a process graph where the minor labels contain the
// container name, if found.
func (r containerWithImageNameRenderer) Render(rpt report.Report) RenderableNodes {
	containers := r.Renderer.Render(rpt)
	images := Map{
		MapFunc:  MapContainerImageIdentity,
		Renderer: SelectContainerImage,
	}.Render(rpt)

	for id, c := range containers {
		imageID, ok := c.Node.Metadata[docker.ImageID]
		if !ok {
			continue
		}
		image, ok := images[imageID]
		if !ok {
			continue
		}
		c.Rank = imageNameWithoutVersion(image.LabelMajor)
		containers[id] = c
	}

	return containers
}

// ContainerWithImageNameRenderer is a Renderer which produces a container
// graph where the ranks are the image names, not their IDs
var ContainerWithImageNameRenderer = containerWithImageNameRenderer{ContainerRenderer}

// ContainerImageRenderer is a Renderer which produces a renderable container
// image graph by merging the container graph and the container image topology.
var ContainerImageRenderer = Map{
	MapFunc: MapCountContainers,
	Renderer: Map{
		MapFunc: MapContainerImage2Name,
		Renderer: MakeReduce(
			Map{
				MapFunc:  MapContainer2ContainerImage,
				Renderer: ContainerRenderer,
			},
			Map{
				MapFunc:  MapContainerImageIdentity,
				Renderer: SelectContainerImage,
			},
		),
	},
}

// ContainerHostnameRenderer is a Renderer which produces a renderable container
// by hostname graph..
var ContainerHostnameRenderer = Map{
	MapFunc: MapCountContainers,
	Renderer: Map{
		MapFunc:  MapContainer2Hostname,
		Renderer: ContainerRenderer,
	},
}

// AddressRenderer is a Renderer which produces a renderable address
// graph from the address topology.
var AddressRenderer = Map{
	MapFunc:  MapAddressIdentity,
	Renderer: SelectAddress,
}

// HostRenderer is a Renderer which produces a renderable host
// graph from the host topology and address graph.
var HostRenderer = MakeReduce(
	Map{
		MapFunc:  MapAddress2Host,
		Renderer: AddressRenderer,
	},
	Map{
		MapFunc:  MapHostIdentity,
		Renderer: SelectHost,
	},
)

// PodRenderer is a Renderer which produces a renderable kubernetes
// graph by merging the container graph and the pods topology.
var PodRenderer = Map{
	MapFunc: MapCountContainers,
	Renderer: MakeReduce(
		Map{
			MapFunc:  MapPodIdentity,
			Renderer: SelectPod,
		},
		Map{
			MapFunc:  MapContainer2Pod,
			Renderer: ContainerRenderer,
		},
	),
}

// PodServiceRenderer is a Renderer which produces a renderable kubernetes services
// graph by merging the pods graph and the services topology.
var PodServiceRenderer = Map{
	MapFunc: MapCountPods,
	Renderer: MakeReduce(
		Map{
			MapFunc:  MapPod2Service,
			Renderer: PodRenderer,
		},
		Map{
			MapFunc:  MapServiceIdentity,
			Renderer: SelectService,
		},
	),
}
<commit_msg>Prevent a standed Uncontained node from appearing in container view.<commit_after>package render

import (
	"fmt"

	"github.com/weaveworks/scope/probe/docker"
	"github.com/weaveworks/scope/probe/process"
	"github.com/weaveworks/scope/report"
)

// EndpointRenderer is a Renderer which produces a renderable endpoint graph.
var EndpointRenderer = Map{
	MapFunc:  MapEndpointIdentity,
	Renderer: SelectEndpoint,
}

// ProcessRenderer is a Renderer which produces a renderable process
// graph by merging the endpoint graph and the process topology.
var ProcessRenderer = MakeReduce(
	Map{
		MapFunc:  MapEndpoint2Process,
		Renderer: EndpointRenderer,
	},
	Map{
		MapFunc:  MapProcessIdentity,
		Renderer: SelectProcess,
	},
)

// processWithContainerNameRenderer is a Renderer which produces a process
// graph enriched with container names where appropriate
type processWithContainerNameRenderer struct {
	Renderer
}

func (r processWithContainerNameRenderer) Render(rpt report.Report) RenderableNodes {
	processes := r.Renderer.Render(rpt)
	containers := Map{
		MapFunc:  MapContainerIdentity,
		Renderer: SelectContainer,
	}.Render(rpt)

	for id, p := range processes {
		pid, ok := p.Node.Metadata[process.PID]
		if !ok {
			continue
		}
		containerID, ok := p.Node.Metadata[docker.ContainerID]
		if !ok {
			continue
		}
		container, ok := containers[containerID]
		if !ok {
			continue
		}
		p.LabelMinor = fmt.Sprintf("%s (%s:%s)", report.ExtractHostID(p.Node), container.LabelMajor, pid)
		processes[id] = p
	}

	return processes
}

// ProcessWithContainerNameRenderer is a Renderer which produces a process
// graph enriched with container names where appropriate
var ProcessWithContainerNameRenderer = processWithContainerNameRenderer{ProcessRenderer}

// ProcessNameRenderer is a Renderer which produces a renderable process
// name graph by munging the progess graph.
var ProcessNameRenderer = Map{
	MapFunc: MapCountProcessName,
	Renderer: Map{
		MapFunc:  MapProcess2Name,
		Renderer: ProcessRenderer,
	},
}

// ContainerRenderer is a Renderer which produces a renderable container
// graph by merging the process graph and the container topology.
// NB We only want processes in container _or_ processes with network connections
// but we need to be careful to ensure we only include each edge once, by only
// including the ProcessRenderer once.
var ContainerRenderer = MakeReduce(
	Filter{
		FilterFunc: func(n RenderableNode) bool {
			_, inContainer := n.Node.Metadata[docker.ContainerID]
			_, isConnected := n.Node.Metadata[IsConnected]
			return inContainer || isConnected
		},
		Renderer: ColorConnected(Map{
			MapFunc:  MapProcess2Container,
			Renderer: ProcessRenderer,
		}),
	},

	Map{
		MapFunc:  MapContainerIdentity,
		Renderer: SelectContainer,
	},

	// This mapper brings in short lived connections by joining with container IPs.
	// We need to be careful to ensure we only include each edge once.  Edges brought in
	// by the above renders will have a pid, so its enough to filter out any nodes with
	// pids.
	Map{
		MapFunc: MapIP2Container,
		Renderer: FilterUnconnected(
			MakeReduce(
				Map{
					MapFunc:  MapContainer2IP,
					Renderer: SelectContainer,
				},
				Map{
					MapFunc:  MapEndpoint2IP,
					Renderer: SelectEndpoint,
				},
			),
		),
	},
)

type containerWithImageNameRenderer struct {
	Renderer
}

// Render produces a process graph where the minor labels contain the
// container name, if found.
func (r containerWithImageNameRenderer) Render(rpt report.Report) RenderableNodes {
	containers := r.Renderer.Render(rpt)
	images := Map{
		MapFunc:  MapContainerImageIdentity,
		Renderer: SelectContainerImage,
	}.Render(rpt)

	for id, c := range containers {
		imageID, ok := c.Node.Metadata[docker.ImageID]
		if !ok {
			continue
		}
		image, ok := images[imageID]
		if !ok {
			continue
		}
		c.Rank = imageNameWithoutVersion(image.LabelMajor)
		containers[id] = c
	}

	return containers
}

// ContainerWithImageNameRenderer is a Renderer which produces a container
// graph where the ranks are the image names, not their IDs
var ContainerWithImageNameRenderer = containerWithImageNameRenderer{ContainerRenderer}

// ContainerImageRenderer is a Renderer which produces a renderable container
// image graph by merging the container graph and the container image topology.
var ContainerImageRenderer = Map{
	MapFunc: MapCountContainers,
	Renderer: Map{
		MapFunc: MapContainerImage2Name,
		Renderer: MakeReduce(
			Map{
				MapFunc:  MapContainer2ContainerImage,
				Renderer: ContainerRenderer,
			},
			Map{
				MapFunc:  MapContainerImageIdentity,
				Renderer: SelectContainerImage,
			},
		),
	},
}

// ContainerHostnameRenderer is a Renderer which produces a renderable container
// by hostname graph..
var ContainerHostnameRenderer = Map{
	MapFunc: MapCountContainers,
	Renderer: Map{
		MapFunc:  MapContainer2Hostname,
		Renderer: ContainerRenderer,
	},
}

// AddressRenderer is a Renderer which produces a renderable address
// graph from the address topology.
var AddressRenderer = Map{
	MapFunc:  MapAddressIdentity,
	Renderer: SelectAddress,
}

// HostRenderer is a Renderer which produces a renderable host
// graph from the host topology and address graph.
var HostRenderer = MakeReduce(
	Map{
		MapFunc:  MapAddress2Host,
		Renderer: AddressRenderer,
	},
	Map{
		MapFunc:  MapHostIdentity,
		Renderer: SelectHost,
	},
)

// PodRenderer is a Renderer which produces a renderable kubernetes
// graph by merging the container graph and the pods topology.
var PodRenderer = Map{
	MapFunc: MapCountContainers,
	Renderer: MakeReduce(
		Map{
			MapFunc:  MapPodIdentity,
			Renderer: SelectPod,
		},
		Map{
			MapFunc:  MapContainer2Pod,
			Renderer: ContainerRenderer,
		},
	),
}

// PodServiceRenderer is a Renderer which produces a renderable kubernetes services
// graph by merging the pods graph and the services topology.
var PodServiceRenderer = Map{
	MapFunc: MapCountPods,
	Renderer: MakeReduce(
		Map{
			MapFunc:  MapPod2Service,
			Renderer: PodRenderer,
		},
		Map{
			MapFunc:  MapServiceIdentity,
			Renderer: SelectService,
		},
	),
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. 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 zoekt

import (
	"log"
	"sort"
)

var _ = log.Println

type contentProvider struct {
	reader   *reader
	id       *indexData
	idx      uint32
	stats    *Stats
	_cb      []byte
	_data    []byte
	_nl      []uint32
	fileSize uint32
}

func (p *contentProvider) newlines() []uint32 {
	if p._nl == nil {
		p._nl = p.reader.readNewlines(p.id, p.idx)
	}
	return p._nl
}

func (p *contentProvider) data(fileName bool) []byte {
	if fileName {
		return p.id.fileNameContent[p.id.fileNameIndex[p.idx]:p.id.fileNameIndex[p.idx+1]]
	}

	if p._data == nil {
		p._data = p.reader.readContents(p.id, p.idx)
		p.stats.FilesLoaded++
		p.stats.BytesLoaded += int64(len(p._data))
	}
	return p._data
}

func (p *contentProvider) caseBits(fileName bool) []byte {
	if fileName {
		return p.id.fileNameCaseBits[p.id.fileNameCaseBitsIndex[p.idx]:p.id.fileNameCaseBitsIndex[p.idx+1]]
	}

	if p._cb == nil {
		p._cb = p.reader.readCaseBits(p.id, p.idx)
	}
	return p._cb
}

func (p *contentProvider) caseMatches(m *candidateMatch) bool {
	return m.caseMatches(p.caseBits(m.fileName))
}

func (p *contentProvider) matchContent(m *candidateMatch) bool {
	return m.matchContent(p.data(m.fileName))
}

func (p *contentProvider) fillMatch(m *candidateMatch) Match {
	var finalMatch Match
	if m.fileName {
		finalMatch = Match{
			Offset:      m.offset,
			Line:        p.data(true),
			LineOff:     int(m.offset),
			MatchLength: int(m.matchSz),
			FileName:    true,
		}
	} else {
		num, start, end := m.line(p.newlines(), p.fileSize)
		finalMatch = Match{
			Offset:      m.offset,
			LineStart:   start,
			LineEnd:     end,
			LineNum:     num,
			LineOff:     int(m.offset) - start,
			MatchLength: int(m.matchSz),
		}
		finalMatch.Line = toOriginal(p.data(false), p.caseBits(false), start, end)
	}

	finalMatch.Score = matchScore(&finalMatch)

	return finalMatch
}

const (
	// TODO - how to anchor this relative to rank?
	scorePartialWordMatch = 5000.0
	scoreWordMatch        = 50000.0
)

func matchScore(m *Match) float64 {
	startBoundary := m.LineOff == 0 || byteClass(m.Line[m.LineOff-1]) != byteClass(m.Line[m.LineOff])

	end := int(m.LineOff) + m.MatchLength
	endBoundary := end == len(m.Line) || byteClass(m.Line[end-1]) != byteClass(m.Line[end])

	if startBoundary && endBoundary {
		return scoreWordMatch
	} else if startBoundary || endBoundary {
		return scorePartialWordMatch
	}

	return 0.0
}

type matchScoreSlice []Match

func (m matchScoreSlice) Len() int           { return len(m) }
func (m matchScoreSlice) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
func (m matchScoreSlice) Less(i, j int) bool { return m[i].Score > m[j].Score }

type fileMatchSlice []FileMatch

func (m fileMatchSlice) Len() int           { return len(m) }
func (m fileMatchSlice) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
func (m fileMatchSlice) Less(i, j int) bool { return m[i].Score > m[j].Score }

func sortMatchesByScore(ms []Match) {
	sort.Sort(matchScoreSlice(ms))
}

func sortFilesByScore(ms []FileMatch) {
	sort.Sort(fileMatchSlice(ms))
}
<commit_msg>Add extra logging to catch Heisenbug.<commit_after>// Copyright 2016 Google Inc. 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 zoekt

import (
	"log"
	"sort"
)

var _ = log.Println

type contentProvider struct {
	reader   *reader
	id       *indexData
	idx      uint32
	stats    *Stats
	_cb      []byte
	_data    []byte
	_nl      []uint32
	fileSize uint32
}

func (p *contentProvider) newlines() []uint32 {
	if p._nl == nil {
		p._nl = p.reader.readNewlines(p.id, p.idx)
	}
	return p._nl
}

func (p *contentProvider) data(fileName bool) []byte {
	if fileName {
		return p.id.fileNameContent[p.id.fileNameIndex[p.idx]:p.id.fileNameIndex[p.idx+1]]
	}

	if p._data == nil {
		p._data = p.reader.readContents(p.id, p.idx)
		p.stats.FilesLoaded++
		p.stats.BytesLoaded += int64(len(p._data))
	}
	return p._data
}

func (p *contentProvider) caseBits(fileName bool) []byte {
	if fileName {
		return p.id.fileNameCaseBits[p.id.fileNameCaseBitsIndex[p.idx]:p.id.fileNameCaseBitsIndex[p.idx+1]]
	}

	if p._cb == nil {
		p._cb = p.reader.readCaseBits(p.id, p.idx)
	}
	return p._cb
}

func (p *contentProvider) caseMatches(m *candidateMatch) bool {
	return m.caseMatches(p.caseBits(m.fileName))
}

func (p *contentProvider) matchContent(m *candidateMatch) bool {
	return m.matchContent(p.data(m.fileName))
}

func (p *contentProvider) fillMatch(m *candidateMatch) Match {
	var finalMatch Match
	if m.fileName {
		finalMatch = Match{
			Offset:      m.offset,
			Line:        p.data(true),
			LineOff:     int(m.offset),
			MatchLength: int(m.matchSz),
			FileName:    true,
		}
	} else {
		num, start, end := m.line(p.newlines(), p.fileSize)
		finalMatch = Match{
			Offset:      m.offset,
			LineStart:   start,
			LineEnd:     end,
			LineNum:     num,
			LineOff:     int(m.offset) - start,
			MatchLength: int(m.matchSz),
		}
		finalMatch.Line = toOriginal(p.data(false), p.caseBits(false), start, end)
	}

	finalMatch.Score = matchScore(&finalMatch)

	return finalMatch
}

const (
	// TODO - how to anchor this relative to rank?
	scorePartialWordMatch = 5000.0
	scoreWordMatch        = 50000.0
)

func matchScore(m *Match) float64 {
	startBoundary := m.LineOff == 0 || byteClass(m.Line[m.LineOff-1]) != byteClass(m.Line[m.LineOff])

	end := int(m.LineOff) + m.MatchLength
	if end < 1 || end > len(m.Line) {
		// I see an occasional out-of-bounds panic when
		// computing endBoundary. Since the problem is not
		// reproducible, try to gather some more data.
		log.Panicf("end %d out of bounds (l %d), match: %#v", end, len(m.Line), m)
	}

	endBoundary := end == len(m.Line) || byteClass(m.Line[end-1]) != byteClass(m.Line[end])

	if startBoundary && endBoundary {
		return scoreWordMatch
	} else if startBoundary || endBoundary {
		return scorePartialWordMatch
	}

	return 0.0
}

type matchScoreSlice []Match

func (m matchScoreSlice) Len() int           { return len(m) }
func (m matchScoreSlice) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
func (m matchScoreSlice) Less(i, j int) bool { return m[i].Score > m[j].Score }

type fileMatchSlice []FileMatch

func (m fileMatchSlice) Len() int           { return len(m) }
func (m fileMatchSlice) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
func (m fileMatchSlice) Less(i, j int) bool { return m[i].Score > m[j].Score }

func sortMatchesByScore(ms []Match) {
	sort.Sort(matchScoreSlice(ms))
}

func sortFilesByScore(ms []FileMatch) {
	sort.Sort(fileMatchSlice(ms))
}
<|endoftext|>


<commit_before>package slack

import (
	"context"
	"errors"
	"net/url"
	"strconv"
)

const (
	DEFAULT_SEARCH_SORT      = "score"
	DEFAULT_SEARCH_SORT_DIR  = "desc"
	DEFAULT_SEARCH_HIGHLIGHT = false
	DEFAULT_SEARCH_COUNT     = 100
	DEFAULT_SEARCH_PAGE      = 1
)

type SearchParameters struct {
	Sort          string
	SortDirection string
	Highlight     bool
	Count         int
	Page          int
}

type CtxChannel struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

type CtxMessage struct {
	User      string `json:"user"`
	Username  string `json:"username"`
	Text      string `json:"text"`
	Timestamp string `json:"ts"`
	Type      string `json:"type"`
}

type SearchMessage struct {
	Type      string     `json:"type"`
	Channel   CtxChannel `json:"channel"`
	User      string     `json:"user"`
	Username  string     `json:"username"`
	Timestamp string     `json:"ts"`
	Text      string     `json:"text"`
	Permalink string     `json:"permalink"`
	Previous  CtxMessage `json:"previous"`
	Previous2 CtxMessage `json:"previous_2"`
	Next      CtxMessage `json:"next"`
	Next2     CtxMessage `json:"next_2"`
}

type SearchMessages struct {
	Matches    []SearchMessage `json:"matches"`
	Paging     `json:"paging"`
	Pagination `json:"pagination"`
	Total      int `json:"total"`
}

type SearchFiles struct {
	Matches    []File `json:"matches"`
	Paging     `json:"paging"`
	Pagination `json:"pagination"`
	Total      int `json:"total"`
}

type searchResponseFull struct {
	Query          string `json:"query"`
	SearchMessages `json:"messages"`
	SearchFiles    `json:"files"`
	SlackResponse
}

func NewSearchParameters() SearchParameters {
	return SearchParameters{
		Sort:          DEFAULT_SEARCH_SORT,
		SortDirection: DEFAULT_SEARCH_SORT_DIR,
		Highlight:     DEFAULT_SEARCH_HIGHLIGHT,
		Count:         DEFAULT_SEARCH_COUNT,
		Page:          DEFAULT_SEARCH_PAGE,
	}
}

func (api *Client) _search(ctx context.Context, path, query string, params SearchParameters, files, messages bool) (response *searchResponseFull, error error) {
	values := url.Values{
		"token": {api.token},
		"query": {query},
	}
	if params.Sort != DEFAULT_SEARCH_SORT {
		values.Add("sort", params.Sort)
	}
	if params.SortDirection != DEFAULT_SEARCH_SORT_DIR {
		values.Add("sort_dir", params.SortDirection)
	}
	if params.Highlight != DEFAULT_SEARCH_HIGHLIGHT {
		values.Add("highlight", strconv.Itoa(1))
	}
	if params.Count != DEFAULT_SEARCH_COUNT {
		values.Add("count", strconv.Itoa(params.Count))
	}
	if params.Page != DEFAULT_SEARCH_PAGE {
		values.Add("page", strconv.Itoa(params.Page))
	}

	response = &searchResponseFull{}
	err := post(ctx, api.httpclient, path, values, response, api.debug)
	if err != nil {
		return nil, err
	}
	if !response.Ok {
		return nil, errors.New(response.Error)
	}
	return response, nil

}

func (api *Client) Search(query string, params SearchParameters) (*SearchMessages, *SearchFiles, error) {
	return api.SearchContext(context.Background(), query, params)
}

func (api *Client) SearchContext(ctx context.Context, query string, params SearchParameters) (*SearchMessages, *SearchFiles, error) {
	response, err := api._search(ctx, "search.all", query, params, true, true)
	if err != nil {
		return nil, nil, err
	}
	return &response.SearchMessages, &response.SearchFiles, nil
}

func (api *Client) SearchFiles(query string, params SearchParameters) (*SearchFiles, error) {
	return api.SearchFilesContext(context.Background(), query, params)
}

func (api *Client) SearchFilesContext(ctx context.Context, query string, params SearchParameters) (*SearchFiles, error) {
	response, err := api._search(ctx, "search.files", query, params, true, false)
	if err != nil {
		return nil, err
	}
	return &response.SearchFiles, nil
}

func (api *Client) SearchMessages(query string, params SearchParameters) (*SearchMessages, error) {
	return api.SearchMessagesContext(context.Background(), query, params)
}

func (api *Client) SearchMessagesContext(ctx context.Context, query string, params SearchParameters) (*SearchMessages, error) {
	response, err := api._search(ctx, "search.messages", query, params, false, true)
	if err != nil {
		return nil, err
	}
	return &response.SearchMessages, nil
}
<commit_msg>Parse attachments returned during message search<commit_after>package slack

import (
	"context"
	"errors"
	"net/url"
	"strconv"
)

const (
	DEFAULT_SEARCH_SORT      = "score"
	DEFAULT_SEARCH_SORT_DIR  = "desc"
	DEFAULT_SEARCH_HIGHLIGHT = false
	DEFAULT_SEARCH_COUNT     = 100
	DEFAULT_SEARCH_PAGE      = 1
)

type SearchParameters struct {
	Sort          string
	SortDirection string
	Highlight     bool
	Count         int
	Page          int
}

type CtxChannel struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

type CtxMessage struct {
	User      string `json:"user"`
	Username  string `json:"username"`
	Text      string `json:"text"`
	Timestamp string `json:"ts"`
	Type      string `json:"type"`
}

type SearchMessage struct {
	Type        string       `json:"type"`
	Channel     CtxChannel   `json:"channel"`
	User        string       `json:"user"`
	Username    string       `json:"username"`
	Timestamp   string       `json:"ts"`
	Text        string       `json:"text"`
	Permalink   string       `json:"permalink"`
	Attachments []Attachment `json:"attachments"`
	Previous    CtxMessage   `json:"previous"`
	Previous2   CtxMessage   `json:"previous_2"`
	Next        CtxMessage   `json:"next"`
	Next2       CtxMessage   `json:"next_2"`
}

type SearchMessages struct {
	Matches    []SearchMessage `json:"matches"`
	Paging     `json:"paging"`
	Pagination `json:"pagination"`
	Total      int `json:"total"`
}

type SearchFiles struct {
	Matches    []File `json:"matches"`
	Paging     `json:"paging"`
	Pagination `json:"pagination"`
	Total      int `json:"total"`
}

type searchResponseFull struct {
	Query          string `json:"query"`
	SearchMessages `json:"messages"`
	SearchFiles    `json:"files"`
	SlackResponse
}

func NewSearchParameters() SearchParameters {
	return SearchParameters{
		Sort:          DEFAULT_SEARCH_SORT,
		SortDirection: DEFAULT_SEARCH_SORT_DIR,
		Highlight:     DEFAULT_SEARCH_HIGHLIGHT,
		Count:         DEFAULT_SEARCH_COUNT,
		Page:          DEFAULT_SEARCH_PAGE,
	}
}

func (api *Client) _search(ctx context.Context, path, query string, params SearchParameters, files, messages bool) (response *searchResponseFull, error error) {
	values := url.Values{
		"token": {api.token},
		"query": {query},
	}
	if params.Sort != DEFAULT_SEARCH_SORT {
		values.Add("sort", params.Sort)
	}
	if params.SortDirection != DEFAULT_SEARCH_SORT_DIR {
		values.Add("sort_dir", params.SortDirection)
	}
	if params.Highlight != DEFAULT_SEARCH_HIGHLIGHT {
		values.Add("highlight", strconv.Itoa(1))
	}
	if params.Count != DEFAULT_SEARCH_COUNT {
		values.Add("count", strconv.Itoa(params.Count))
	}
	if params.Page != DEFAULT_SEARCH_PAGE {
		values.Add("page", strconv.Itoa(params.Page))
	}

	response = &searchResponseFull{}
	err := post(ctx, api.httpclient, path, values, response, api.debug)
	if err != nil {
		return nil, err
	}
	if !response.Ok {
		return nil, errors.New(response.Error)
	}
	return response, nil

}

func (api *Client) Search(query string, params SearchParameters) (*SearchMessages, *SearchFiles, error) {
	return api.SearchContext(context.Background(), query, params)
}

func (api *Client) SearchContext(ctx context.Context, query string, params SearchParameters) (*SearchMessages, *SearchFiles, error) {
	response, err := api._search(ctx, "search.all", query, params, true, true)
	if err != nil {
		return nil, nil, err
	}
	return &response.SearchMessages, &response.SearchFiles, nil
}

func (api *Client) SearchFiles(query string, params SearchParameters) (*SearchFiles, error) {
	return api.SearchFilesContext(context.Background(), query, params)
}

func (api *Client) SearchFilesContext(ctx context.Context, query string, params SearchParameters) (*SearchFiles, error) {
	response, err := api._search(ctx, "search.files", query, params, true, false)
	if err != nil {
		return nil, err
	}
	return &response.SearchFiles, nil
}

func (api *Client) SearchMessages(query string, params SearchParameters) (*SearchMessages, error) {
	return api.SearchMessagesContext(context.Background(), query, params)
}

func (api *Client) SearchMessagesContext(ctx context.Context, query string, params SearchParameters) (*SearchMessages, error) {
	response, err := api._search(ctx, "search.messages", query, params, false, true)
	if err != nil {
		return nil, err
	}
	return &response.SearchMessages, nil
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016 aerth
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// package seconf allows your software to store non-plaintext configuration files.
//
// check out the example application in _examples/hello for a working example.
//
//		 fmt.Println("Welcome to " + sn + ", " + configarray[0])
//		 fmt.Printf("Your %s is %s \n", os.Args[3], configarray[0])
//		 fmt.Printf("Your %s is %s \n", os.Args[4], configarray[1])
//		 fmt.Printf("Your %s is %s \n", os.Args[5], configarray[2])
package seconf

import (
	"bufio"
	"crypto/rand"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"errors"

	"github.com/bgentry/speakeasy"
	"golang.org/x/crypto/nacl/secretbox"
)

const keySize = 32
const nonceSize = 24

// secustom is the filename that gets stored. for example, if secustom is "test", the configuration file will be saved as $HOME/.test
var secustom string
var username string
var password string
var hashbar = strings.Repeat("#", 80)

var configuser = ""
var configpass = ""

var configlock = ""

// Seconf is the struct for the seconf pathname and fields.
type Seconf struct {
	Id   int64
	Path string
	Args []string
}

/*
type Fielder struct {
	Id       int64
	Name     string
	Password bool
}
*/

// constainsString returns true if a slice contains a string.
func containsString(slice []string, element string) bool {
	return !(posString(slice, element) == -1)
}

// askForConfirmation returns true if the user types one of the "okayResponses"
// https://gist.github.com/albrow/5882501
func askForConfirmation() bool {
	var response string

	_, err := fmt.Scanln(&response)
	if err != nil {
		//fmt.Println(err)
		return false
	}
	okayResponses := []string{"y", "Y", "yes", "Yes", "YES"}
	nokayResponses := []string{"n", "N", "no", "No", "NO", "\n"}
	quitResponses := []string{"q", "Q", "exit", "quit"}
	if containsString(okayResponses, response) {
		return true
	} else if containsString(nokayResponses, response) {
		return false
	} else if containsString(quitResponses, response) {
		return false
	} else {
		fmt.Println("\nNot valid answer, try again. [y/n] [yes/no]")
		return askForConfirmation()
	}
}

// posString returns the first index of element in slice.
// If slice does not contain element, returns -1.
func posString(slice []string, element string) int {
	for index, elem := range slice {
		if elem == element {
			return index
		}
	}
	return -1
}

// Prompt the user for the particular field.
func Prompt(header string) string {
	fmt.Printf("\n### " + header + " ###\n")
	fmt.Printf("\nPress ENTER when you are finished typing.\n\n")
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		line := scanner.Text()
		return line
	}
	if err := scanner.Err(); err != nil {
		fmt.Println(err)
		return Prompt(header)
	}
	return ""
}

// Create initializes a new configuration file, at $HOME/secustom with the title servicename and as many fields as needed. Any field starting with "pass" will be assumed a password and input will not be echoed.
func Create(secustom string, servicename string, arg ...string) {
	bar(servicename)
	configfields := &Seconf{
		Path: secustom,
		Args: arg,
	}

	var m1 map[int]string = map[int]string{}
	var newsplice []string
	for i := range configfields.Args {
		bar(servicename)
		if len(configfields.Args[i]) > 4 {
			if configfields.Args[i][0:4] == "pass" || configfields.Args[i][0:4] == "Pass" {
				//		fmt.Printf("\n### " + servicename + " ###\n")
				m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				if m1[i] == "" {
					bar(secustom)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(secustom)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(secustom)
					fmt.Println(configfields.Args[i] + " cannot be blank.")
					return
				}

			} else {
				m1[i] = Prompt(configfields.Args[i])
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					fmt.Println(configfields.Args[i] + " cannot be blank.")
					return
				}
			}
		} else {
			m1[i] = Prompt(configfields.Args[i])
		}
		newsplice = append(newsplice, m1[i]+"::::")
	}

	bar(servicename)
	configlock, _ := speakeasy.Ask("Create a password to encrypt config file:\nPress ENTER for no password.")
	var userKey = configlock
	var pad = []byte("«super jumpy fox jumps all over»")

	var messagebox = strings.Join(newsplice, "")
	messagebox = strings.TrimSuffix(messagebox, "::::")
	var message = []byte(messagebox)
	key := []byte(userKey)
	key = append(key, pad...)
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])
	nonce := new([nonceSize]byte)
	// Read bytes from random and put them in nonce until it is full.
	_, err := io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		fmt.Println("Could not read from random:", err)
		return
	}
	out := make([]byte, nonceSize)
	copy(out, nonce[:])
	out = secretbox.Seal(out, message, nonce, naclKey)
	err = ioutil.WriteFile(ReturnHome()+"/."+secustom, out, 0600)
	if err != nil {
		fmt.Println("Error while writing config file: ", err)
		return
	}
	fmt.Printf("Config file saved at "+ReturnHome()+"/."+secustom+" \nTotal size is %d bytes.\n",
		len(out))
	os.Exit(0)
}

// Detect returns TRUE if a seconf file exists.
func Detect(secustom string) bool {
	_, err := ioutil.ReadFile(ReturnHome() + "/." + secustom)
	if err != nil {
		return false
	}
	return true
}

// Read returns the decoded configuration file, or an error. Fields are separated by 4 colons. ("::::")
func Read(secustom string) (config string, err error) {
	bar(secustom)
	fmt.Println("Unlocking config file")
	configlock, err = speakeasy.Ask("Password: ")
	bar(secustom)
	var userKey = configlock
	var pad = []byte("«super jumpy fox jumps all over»")
	key := []byte(userKey)
	key = append(key, pad...)
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])
	nonce := new([nonceSize]byte)
	in, err := ioutil.ReadFile(ReturnHome() + "/." + secustom)
	if err != nil {
		fmt.Println(err)

	}
	copy(nonce[:], in[:nonceSize])
	configbytes, ok := secretbox.Open(nil, in[nonceSize:], nonce, naclKey)
	if !ok {
		return "", errors.New("Could not decrypt the config file. Wrong password?")
	}
	return string(configbytes), nil

}

// Cheap and effective way of clearing screen on unix. Ugly on windows.
func bar(secustom string) {
	versionbar := strings.Repeat("#", 10) + "\t" + secustom + "\t" + strings.Repeat("#", 30)
	print("\033[H\033[2J")
	fmt.Println(versionbar)
}

// ReturnHome is a cross-OS way of getting a HOMEDIR.
func ReturnHome() (homedir string) {
	homedir = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
	if homedir == "" {
		homedir = os.Getenv("USERPROFILE")
	}
	if homedir == "" {
		homedir = os.Getenv("HOME")
	}
	return
}

// Lock() is the new version of Create(), It returns any errors during the process instead of using os.Exit()
func Lock(secustom string, servicename string, arg ...string) error {
	bar(servicename)
	configfields := &Seconf{
		Path: secustom,
		Args: arg,
	}

	var m1 map[int]string = map[int]string{}
	var newsplice []string
	for i := range configfields.Args {
		bar(servicename)
		if len(configfields.Args[i]) > 4 {
			if configfields.Args[i][0:4] == "pass" || configfields.Args[i][0:4] == "Pass" {
				m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				if m1[i] == "" {
					bar(servicename)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(servicename)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(servicename)
					return errors.New(configfields.Args[i] + " cannot be blank.")
				}

			} else {
				m1[i] = Prompt(configfields.Args[i])
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					return errors.New(configfields.Args[i] + " cannot be blank.")
				}
			}
		} else {
			m1[i] = Prompt(configfields.Args[i])
		}
		newsplice = append(newsplice, m1[i]+"::::")
	}
	bar(servicename)
	configlock, _ := speakeasy.Ask("Create a password to encrypt config file:\nPress ENTER for no password.")
	var userKey = configlock
	var pad = []byte("«super jumpy fox jumps all over»")

	var messagebox = strings.Join(newsplice, "")
	messagebox = strings.TrimSuffix(messagebox, "::::")
	var message = []byte(messagebox)
	key := []byte(userKey)
	key = append(key, pad...)
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])
	nonce := new([nonceSize]byte)
	// Read bytes from random and put them in nonce until it is full.
	_, err := io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		return errors.New("Could not read from random: "+err.Error())
	}
	out := make([]byte, nonceSize)
	copy(out, nonce[:])
	out = secretbox.Seal(out, message, nonce, naclKey)
	err = ioutil.WriteFile(ReturnHome()+"/."+secustom, out, 0600)
	if err != nil {
		return errors.New("Error while writing config file: "+err.Error())
	}
	fmt.Printf("Config file saved at "+ReturnHome()+"/."+secustom+" \nTotal size is %d bytes.\n", len(out))
	return nil
}

func Destroy(secustom string) error {
	fmt.Println("Are you sure you want to remove "+ReturnHome()+"/."+secustom+" file?")
if askForConfirmation(){
	if Detect(secustom) {
	os.Remove(ReturnHome()+"/."+secustom)
	return nil
	}
	return errors.New("Errorr!")
}
return errors.New("Error")
}
<commit_msg>Remove bars / terminal resets (fix commit email)<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 aerth
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// package seconf allows your software to store non-plaintext configuration files.
//
// check out the example application in _examples/hello for a working example.
//
//		 fmt.Println("Welcome to " + sn + ", " + configarray[0])
//		 fmt.Printf("Your %s is %s \n", os.Args[3], configarray[0])
//		 fmt.Printf("Your %s is %s \n", os.Args[4], configarray[1])
//		 fmt.Printf("Your %s is %s \n", os.Args[5], configarray[2])
package seconf

import (
	"bufio"
	"crypto/rand"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"errors"

	"github.com/bgentry/speakeasy"
	"golang.org/x/crypto/nacl/secretbox"
)

const keySize = 32
const nonceSize = 24

// secustom is the filename that gets stored. for example, if secustom is "test", the configuration file will be saved as $HOME/.test
var secustom string
var username string
var password string
var hashbar = strings.Repeat("#", 80)

var configuser = ""
var configpass = ""

var configlock = ""

// Seconf is the struct for the seconf pathname and fields.
type Seconf struct {
	Id   int64
	Path string
	Args []string
}

/*
type Fielder struct {
	Id       int64
	Name     string
	Password bool
}
*/

// constainsString returns true if a slice contains a string.
func containsString(slice []string, element string) bool {
	return !(posString(slice, element) == -1)
}

// askForConfirmation returns true if the user types one of the "okayResponses"
// https://gist.github.com/albrow/5882501
func askForConfirmation() bool {
	var response string

	_, err := fmt.Scanln(&response)
	if err != nil {
		//fmt.Println(err)
		return false
	}
	okayResponses := []string{"y", "Y", "yes", "Yes", "YES"}
	nokayResponses := []string{"n", "N", "no", "No", "NO", "\n"}
	quitResponses := []string{"q", "Q", "exit", "quit"}
	if containsString(okayResponses, response) {
		return true
	} else if containsString(nokayResponses, response) {
		return false
	} else if containsString(quitResponses, response) {
		return false
	} else {
		fmt.Println("\nNot valid answer, try again. [y/n] [yes/no]")
		return askForConfirmation()
	}
}

// posString returns the first index of element in slice.
// If slice does not contain element, returns -1.
func posString(slice []string, element string) int {
	for index, elem := range slice {
		if elem == element {
			return index
		}
	}
	return -1
}

// Prompt the user for the particular field.
func Prompt(header string) string {
	fmt.Printf("\n### " + header + " ###\n")
	fmt.Printf("\nPress ENTER when you are finished typing.\n\n")
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		line := scanner.Text()
		return line
	}
	if err := scanner.Err(); err != nil {
		fmt.Println(err)
		return Prompt(header)
	}
	return ""
}

// Create initializes a new configuration file, at $HOME/secustom with the title servicename and as many fields as needed. Any field starting with "pass" will be assumed a password and input will not be echoed.
func Create(secustom string, servicename string, arg ...string) {
	bar(servicename)
	configfields := &Seconf{
		Path: secustom,
		Args: arg,
	}

	var m1 map[int]string = map[int]string{}
	var newsplice []string
	for i := range configfields.Args {
		bar(servicename)
		if len(configfields.Args[i]) > 4 {
			if configfields.Args[i][0:4] == "pass" || configfields.Args[i][0:4] == "Pass" {
				//		fmt.Printf("\n### " + servicename + " ###\n")
				m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				if m1[i] == "" {
					bar(secustom)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(secustom)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(secustom)
					fmt.Println(configfields.Args[i] + " cannot be blank.")
					return
				}

			} else {
				m1[i] = Prompt(configfields.Args[i])
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					fmt.Println(configfields.Args[i] + " cannot be blank.")
					return
				}
			}
		} else {
			m1[i] = Prompt(configfields.Args[i])
		}
		newsplice = append(newsplice, m1[i]+"::::")
	}

	bar(servicename)
	configlock, _ := speakeasy.Ask("Create a password to encrypt config file:\nPress ENTER for no password.")
	var userKey = configlock
	var pad = []byte("«super jumpy fox jumps all over»")

	var messagebox = strings.Join(newsplice, "")
	messagebox = strings.TrimSuffix(messagebox, "::::")
	var message = []byte(messagebox)
	key := []byte(userKey)
	key = append(key, pad...)
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])
	nonce := new([nonceSize]byte)
	// Read bytes from random and put them in nonce until it is full.
	_, err := io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		fmt.Println("Could not read from random:", err)
		return
	}
	out := make([]byte, nonceSize)
	copy(out, nonce[:])
	out = secretbox.Seal(out, message, nonce, naclKey)
	err = ioutil.WriteFile(ReturnHome()+"/."+secustom, out, 0600)
	if err != nil {
		fmt.Println("Error while writing config file: ", err)
		return
	}
	fmt.Printf("Config file saved at "+ReturnHome()+"/."+secustom+" \nTotal size is %d bytes.\n",
		len(out))
	os.Exit(0)
}

// Detect returns TRUE if a seconf file exists.
func Detect(secustom string) bool {
	_, err := ioutil.ReadFile(ReturnHome() + "/." + secustom)
	if err != nil {
		return false
	}
	return true
}

// Read returns the decoded configuration file, or an error. Fields are separated by 4 colons. ("::::")
func Read(secustom string) (config string, err error) {
//	bar(secustom)
	fmt.Println("Unlocking config file")
	configlock, err = speakeasy.Ask("Password: ")
//	bar(secustom)
	var userKey = configlock
	var pad = []byte("«super jumpy fox jumps all over»")
	key := []byte(userKey)
	key = append(key, pad...)
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])
	nonce := new([nonceSize]byte)
	in, err := ioutil.ReadFile(ReturnHome() + "/." + secustom)
	if err != nil {
		return "", err
	}
	copy(nonce[:], in[:nonceSize])
	configbytes, ok := secretbox.Open(nil, in[nonceSize:], nonce, naclKey)
	if !ok {
		return "", errors.New("Could not decrypt the config file. Wrong password?")
	}
	return string(configbytes), nil

}

// Cheap and effective way of clearing screen on unix. Ugly on windows.
func bar(secustom string) {
	versionbar := strings.Repeat("#", 10) + "\t" + secustom + "\t" + strings.Repeat("#", 30)
	print("\033[H\033[2J")
	fmt.Println(versionbar)
}

// ReturnHome is a cross-OS way of getting a HOMEDIR.
func ReturnHome() (homedir string) {
	homedir = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
	if homedir == "" {
		homedir = os.Getenv("USERPROFILE")
	}
	if homedir == "" {
		homedir = os.Getenv("HOME")
	}
	return
}

// Lock() is the new version of Create(), It returns any errors during the process instead of using os.Exit()
func Lock(secustom string, servicename string, arg ...string) error {
	bar(servicename)
	configfields := &Seconf{
		Path: secustom,
		Args: arg,
	}

	var m1 map[int]string = map[int]string{}
	var newsplice []string
	for i := range configfields.Args {
		bar(servicename)
		if len(configfields.Args[i]) > 4 {
			if configfields.Args[i][0:4] == "pass" || configfields.Args[i][0:4] == "Pass" {
				m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				if m1[i] == "" {
					bar(servicename)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(servicename)
					m1[i], _ = speakeasy.Ask(servicename + " " + configfields.Args[i] + ": ")
				}
				if m1[i] == "" {
					bar(servicename)
					return errors.New(configfields.Args[i] + " cannot be blank.")
				}

			} else {
				m1[i] = Prompt(configfields.Args[i])
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					fmt.Println("Can not be blank.")
					m1[i] = Prompt(configfields.Args[i])
				}
				if m1[i] == "" {
					bar(servicename)
					return errors.New(configfields.Args[i] + " cannot be blank.")
				}
			}
		} else {
			m1[i] = Prompt(configfields.Args[i])
		}
		newsplice = append(newsplice, m1[i]+"::::")
	}
	bar(servicename)
	configlock, _ := speakeasy.Ask("Create a password to encrypt config file:\nPress ENTER for no password.")
	var userKey = configlock
	var pad = []byte("«super jumpy fox jumps all over»")

	var messagebox = strings.Join(newsplice, "")
	messagebox = strings.TrimSuffix(messagebox, "::::")
	var message = []byte(messagebox)
	key := []byte(userKey)
	key = append(key, pad...)
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])
	nonce := new([nonceSize]byte)
	// Read bytes from random and put them in nonce until it is full.
	_, err := io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		return errors.New("Could not read from random: "+err.Error())
	}
	out := make([]byte, nonceSize)
	copy(out, nonce[:])
	out = secretbox.Seal(out, message, nonce, naclKey)
	err = ioutil.WriteFile(ReturnHome()+"/."+secustom, out, 0600)
	if err != nil {
		return errors.New("Error while writing config file: "+err.Error())
	}
	fmt.Printf("Config file saved at "+ReturnHome()+"/."+secustom+" \nTotal size is %d bytes.\n", len(out))
	return nil
}

func Destroy(secustom string) error {
	fmt.Println("Are you sure you want to remove "+ReturnHome()+"/."+secustom+" file?")
if askForConfirmation(){
	if Detect(secustom) {
	os.Remove(ReturnHome()+"/."+secustom)
	return nil
	}
	return errors.New("Errorr!")
}
return errors.New("Error")
}
<|endoftext|>


<commit_before>package yorm

import (
	"bytes"
	"database/sql"
	"fmt"
	"reflect"
	"strings"
)

var tableSqlMap = map[string]string{}

type sqlScanner interface {
	Scan(dest ...interface{}) error
}

//Select query records(s) from a table.
func Select(i interface{}, condition string, args ...interface{}) error {
	return defaultExecutor.Select(i, condition, args...)
}

//SelectByPK select by pk.
func SelectByPK(i interface{}, tableName ...string) error {
	return defaultExecutor.SelectByPK(i, tableName...)
}

// select by the primary key,the table name param means you can select from other tables
func (ex *executor) SelectByPK(i interface{}, tableName ...string) error {
	iv := reflect.ValueOf(i)

	if !iv.IsValid() {
		return ErrNotSupported
	}
	q, err := newTableSetter(iv)
	if q == nil {
		return err
	}
	table := q.table
	if len(tableName) > 0 {
		table = tableName[0]
	}
	clause := tableSqlMap[table]
	if clause == "" {
		queryClause := buildSelectSql(q, tableName...)
		queryClause.WriteString("WHERE ")
		queryClause.WriteString(q.pkColumn.name)
		queryClause.WriteString("=? LIMIT 1")
		clause = queryClause.String()
		tableSqlMap[table] = clause
	}
	return ex.query(i, clause, iv.Elem().FieldByName(q.pkColumn.fieldName).Int())
}

func Count(i interface{}, where ...interface{}) int64 {
	// i maybe not ptr
	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return 0
	}
	var count int64
	if len(where) > 0 {
		Select(&count, fmt.Sprintf("select count(0) from %s %s", q.table, where[0].(string)), where[1:]...)
	} else {
		Select(&count, fmt.Sprintf("select count(0) from %s", q.table))
	}
	return count
}

func R(i interface{}, cond ...interface{}) error {
	return defaultExecutor.R(i, cond...)
}

// the s method is a super method,easy but not so fast
func (ex *executor) R(i interface{}, cond ...interface{}) error {
	var typ reflect.Type
	var q *tableSetter
	var err error

	q, err = newTableSetter(reflect.ValueOf(i))
	if q == nil {
		typ, q, err = newTableSetterBySlice(i)
		if typ == nil {
			return err
		}
	}

	switch len(cond) {
	case 0:
		if typ == nil {
			return ex.SelectByPK(i)
		} else {
			return ex.Select(i, buildSelectSql(q).String())
		}
	default:
		if reflect.TypeOf(cond[0]).Kind() != reflect.String {
			return ErrIllegalParams
		}
		return ex.Select(i, cond[0].(string), cond[1:]...)
	}
}
func (ex *tranExecutor) Select(i interface{}, condition string, args ...interface{}) error {
	if ex == nil {
		return ErrNilMethodReceiver
	}

	if strings.HasPrefix(strings.ToUpper(condition), "SELECT") {
		return ex.query(i, condition, args...)
	}

	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return ErrNotSupported
	}
	queryClause := buildSelectSql(q)

	if !strings.HasPrefix(strings.ToUpper(condition), "WHERE") {
		queryClause.WriteString("WHERE ")
	}
	queryClause.WriteString(condition)

	return ex.query(i, queryClause.String(), args...)
}

//Query do a select operation.
// if the is a struct ,you need not write select x,y,z,you need only write the where condition ...
func (ex *executor) Select(i interface{}, condition string, args ...interface{}) error {
	if ex == nil {
		return ErrNilMethodReceiver
	}

	if strings.HasPrefix(strings.ToUpper(condition), "SELECT") {
		return ex.query(i, condition, args...)
	}

	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return ErrNotSupported
	}
	queryClause := buildSelectSql(q)

	if !strings.HasPrefix(strings.ToUpper(condition), "WHERE") {
		queryClause.WriteString("WHERE ")
	}
	queryClause.WriteString(condition)

	return ex.query(i, queryClause.String(), args...)
}

func buildSelectSql(q *tableSetter, tableName ...string) *bytes.Buffer {
	queryClause := bytes.NewBufferString("SELECT ")
	queryClause.WriteString(buildFullColumnSql(q))
	queryClause.WriteString("FROM ")
	queryClause.WriteString(append(tableName, q.table)[0])
	queryClause.WriteString(" ")
	return queryClause
}
func buildFullColumnSql(q *tableSetter) string {
	if q == nil || len(q.columns) == 0 {
		return ""
	}
	queryClause := bytes.NewBuffer([]byte{})
	for loop := 0; loop < len(q.columns); loop++ {
		queryClause.WriteByte(',')
		queryClause.WriteString(q.columns[loop].name)
	}
	queryClause.WriteByte(' ')
	//1 means a ","
	return string(queryClause.Bytes()[1:])
}

//Query do a query operation.
func (ex *tranExecutor) query(i interface{}, query string, args ...interface{}) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()

	if strings.Contains(query, "*") {
		vl := reflect.ValueOf(i)
		if typ.Kind() == reflect.Slice {
			vl = reflect.New(typ.Elem())
		}
		q, _ := newTableSetter(vl)
		query = strings.Replace(query, "*", buildFullColumnSql(q), -1)
	}

	yogger.Debug("%s;%v", query, args)
	if typ.Kind() == reflect.Slice {
		rows, err := ex.Query(query, args...)
		if rows == nil {
			return err
		}
		return queryList(i, rows)
	}
	return queryOne(i, ex.QueryRow(query, args...))

}

//Query do a query operation.
func (ex *executor) query(i interface{}, query string, args ...interface{}) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()

	if strings.Contains(query, "*") {
		vl := reflect.ValueOf(i)
		if typ.Kind() == reflect.Slice {
			vl = reflect.New(typ.Elem())
		}
		q, _ := newTableSetter(vl)
		query = strings.Replace(query, "*", buildFullColumnSql(q), -1)
	}

	var err error
	var stmt *sql.Stmt
	yogger.Debug("%s;%v", query, args)
	stmt, err = ex.getStmt(query)
	if stmt == nil {
		return err
	}
	if typ.Kind() == reflect.Slice {
		rows, err := stmt.Query(args...)
		if rows == nil {
			return err
		}
		return queryList(i, rows)
	}
	return queryOne(i, stmt.QueryRow(args...))

}

func queryOne(i interface{}, row *sql.Row) error {
	if row == nil {
		return ErrIllegalParams
	}
	return convertAssignRow(i, row)
}
func queryList(i interface{}, rows *sql.Rows) error {
	if rows == nil {
		return ErrIllegalParams
	}
	return convertAssignRows(i, rows)
}

func newTableSetterBySlice(i interface{}) (reflect.Type, *tableSetter, error) {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return nil, nil, ErrNonPtr
	}
	typ = typ.Elem()
	if typ.Kind() != reflect.Slice {
		return nil, nil, ErrNonSlice
	}
	typ = typ.Elem()
	if typ.Kind() == reflect.Struct {
		q, e := newTableSetter(reflect.New(typ))
		return typ, q, e
	} else {
		return typ, nil, nil
	}
}

func convertAssignRows(i interface{}, rows *sql.Rows) error {
	typ, q, err := newTableSetterBySlice(i)
	if typ == nil {
		return err
	}
	size := 0
	v := reflect.Indirect(reflect.ValueOf(i))
	for rows.Next() {
		if size >= v.Cap() {
			newCap := v.Cap()
			if newCap == 0 {
				newCap = 1
			} else {
				if newCap < 1024 {
					newCap += newCap
				} else {
					newCap += newCap / 4
				}
			}
			nv := reflect.MakeSlice(v.Type(), v.Len(), newCap)
			reflect.Copy(nv, v)
			v.Set(nv)
		}
		if size >= v.Len() {
			v.SetLen(size + 1)
		}
		st := reflect.New(typ)
		st = st.Elem()
		if q != nil {
			err := scanValue(rows, q, st)
			if err != nil {
				return err
			}
		} else {
			ti := newPtrInterface(typ)
			rows.Scan(ti)
			setValue(st, ti)
		}
		v.Index(size).Set(st)
		size++
	}
	return nil
}
func convertAssignRow(i interface{}, row *sql.Row) error {
	typ := reflect.TypeOf(i)

	if typ.Kind() == reflect.Ptr && typ.Elem().Kind() != reflect.Struct {
		return row.Scan(i)
	}

	q, err := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return err
	}
	st := reflect.ValueOf(i).Elem()
	return scanValue(row, q, st)
}
<commit_msg>添加错误处理<commit_after>package yorm

import (
	"bytes"
	"database/sql"
	"fmt"
	"reflect"
	"strings"
)

var tableSqlMap = map[string]string{}

type sqlScanner interface {
	Scan(dest ...interface{}) error
}

//Select query records(s) from a table.
func Select(i interface{}, condition string, args ...interface{}) error {
	return defaultExecutor.Select(i, condition, args...)
}

//SelectByPK select by pk.
func SelectByPK(i interface{}, tableName ...string) error {
	return defaultExecutor.SelectByPK(i, tableName...)
}

// select by the primary key,the table name param means you can select from other tables
func (ex *executor) SelectByPK(i interface{}, tableName ...string) error {
	iv := reflect.ValueOf(i)

	if !iv.IsValid() {
		return ErrNotSupported
	}
	q, err := newTableSetter(iv)
	if q == nil {
		return err
	}
	table := q.table
	if len(tableName) > 0 {
		table = tableName[0]
	}
	clause := tableSqlMap[table]
	if clause == "" {
		queryClause := buildSelectSql(q, tableName...)
		queryClause.WriteString("WHERE ")
		queryClause.WriteString(q.pkColumn.name)
		queryClause.WriteString("=? LIMIT 1")
		clause = queryClause.String()
		tableSqlMap[table] = clause
	}
	return ex.query(i, clause, iv.Elem().FieldByName(q.pkColumn.fieldName).Int())
}

func Count(i interface{}, where ...interface{}) int64 {
	// i maybe not ptr
	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return 0
	}
	var count int64
	if len(where) > 0 {
		Select(&count, fmt.Sprintf("select count(0) from %s %s", q.table, where[0].(string)), where[1:]...)
	} else {
		Select(&count, fmt.Sprintf("select count(0) from %s", q.table))
	}
	return count
}

func R(i interface{}, cond ...interface{}) error {
	return defaultExecutor.R(i, cond...)
}

// the s method is a super method,easy but not so fast
func (ex *executor) R(i interface{}, cond ...interface{}) error {
	var typ reflect.Type
	var q *tableSetter
	var err error

	q, err = newTableSetter(reflect.ValueOf(i))
	if q == nil {
		typ, q, err = newTableSetterBySlice(i)
		if typ == nil {
			return err
		}
	}

	switch len(cond) {
	case 0:
		if typ == nil {
			return ex.SelectByPK(i)
		} else {
			return ex.Select(i, buildSelectSql(q).String())
		}
	default:
		if reflect.TypeOf(cond[0]).Kind() != reflect.String {
			return ErrIllegalParams
		}
		return ex.Select(i, cond[0].(string), cond[1:]...)
	}
}
func (ex *tranExecutor) Select(i interface{}, condition string, args ...interface{}) error {
	if ex == nil {
		return ErrNilMethodReceiver
	}

	if strings.HasPrefix(strings.ToUpper(condition), "SELECT") {
		return ex.query(i, condition, args...)
	}

	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return ErrNotSupported
	}
	queryClause := buildSelectSql(q)

	if !strings.HasPrefix(strings.ToUpper(condition), "WHERE") {
		queryClause.WriteString("WHERE ")
	}
	queryClause.WriteString(condition)

	return ex.query(i, queryClause.String(), args...)
}

//Query do a select operation.
// if the is a struct ,you need not write select x,y,z,you need only write the where condition ...
func (ex *executor) Select(i interface{}, condition string, args ...interface{}) error {
	if ex == nil {
		return ErrNilMethodReceiver
	}

	if strings.HasPrefix(strings.ToUpper(condition), "SELECT") {
		return ex.query(i, condition, args...)
	}

	q, _ := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return ErrNotSupported
	}
	queryClause := buildSelectSql(q)

	if !strings.HasPrefix(strings.ToUpper(condition), "WHERE") {
		queryClause.WriteString("WHERE ")
	}
	queryClause.WriteString(condition)

	return ex.query(i, queryClause.String(), args...)
}

func buildSelectSql(q *tableSetter, tableName ...string) *bytes.Buffer {
	queryClause := bytes.NewBufferString("SELECT ")
	queryClause.WriteString(buildFullColumnSql(q))
	queryClause.WriteString("FROM ")
	queryClause.WriteString(append(tableName, q.table)[0])
	queryClause.WriteString(" ")
	return queryClause
}
func buildFullColumnSql(q *tableSetter) string {
	if q == nil || len(q.columns) == 0 {
		return ""
	}
	queryClause := bytes.NewBuffer([]byte{})
	for loop := 0; loop < len(q.columns); loop++ {
		queryClause.WriteByte(',')
		queryClause.WriteString(q.columns[loop].name)
	}
	queryClause.WriteByte(' ')
	//1 means a ","
	return string(queryClause.Bytes()[1:])
}

//Query do a query operation.
func (ex *tranExecutor) query(i interface{}, query string, args ...interface{}) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()

	if strings.Contains(query, "*") {
		vl := reflect.ValueOf(i)
		if typ.Kind() == reflect.Slice {
			vl = reflect.New(typ.Elem())
		}
		q, _ := newTableSetter(vl)
		query = strings.Replace(query, "*", buildFullColumnSql(q), -1)
	}

	yogger.Debug("%s;%v", query, args)
	if typ.Kind() == reflect.Slice {
		rows, err := ex.Query(query, args...)
		if rows == nil {
			return err
		}
		return queryList(i, rows)
	}
	return queryOne(i, ex.QueryRow(query, args...))

}

//Query do a query operation.
func (ex *executor) query(i interface{}, query string, args ...interface{}) error {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return ErrNonPtr
	}
	typ = typ.Elem()

	if strings.Contains(query, "*") {
		vl := reflect.ValueOf(i)
		if typ.Kind() == reflect.Slice {
			vl = reflect.New(typ.Elem())
		}
		q, _ := newTableSetter(vl)
		query = strings.Replace(query, "*", buildFullColumnSql(q), -1)
	}

	var err error
	var stmt *sql.Stmt
	yogger.Debug("%s;%v", query, args)
	stmt, err = ex.getStmt(query)
	if stmt == nil {
		return err
	}
	if typ.Kind() == reflect.Slice {
		rows, err := stmt.Query(args...)
		if rows == nil {
			return err
		}
		return queryList(i, rows)
	}
	return queryOne(i, stmt.QueryRow(args...))

}

func queryOne(i interface{}, row *sql.Row) error {
	if row == nil {
		return ErrIllegalParams
	}
	return convertAssignRow(i, row)
}
func queryList(i interface{}, rows *sql.Rows) error {
	if rows == nil {
		return ErrIllegalParams
	}
	return convertAssignRows(i, rows)
}

func newTableSetterBySlice(i interface{}) (reflect.Type, *tableSetter, error) {
	typ := reflect.TypeOf(i)
	if typ.Kind() != reflect.Ptr {
		return nil, nil, ErrNonPtr
	}
	typ = typ.Elem()
	if typ.Kind() != reflect.Slice {
		return nil, nil, ErrNonSlice
	}
	typ = typ.Elem()
	if typ.Kind() == reflect.Struct {
		q, e := newTableSetter(reflect.New(typ))
		return typ, q, e
	} else {
		return typ, nil, nil
	}
}

func convertAssignRows(i interface{}, rows *sql.Rows) error {
	typ, q, err := newTableSetterBySlice(i)
	if typ == nil {
		return err
	}
	size := 0
	v := reflect.Indirect(reflect.ValueOf(i))
	for rows.Next() {
		if size >= v.Cap() {
			newCap := v.Cap()
			if newCap == 0 {
				newCap = 1
			} else {
				if newCap < 1024 {
					newCap += newCap
				} else {
					newCap += newCap / 4
				}
			}
			nv := reflect.MakeSlice(v.Type(), v.Len(), newCap)
			reflect.Copy(nv, v)
			v.Set(nv)
		}
		if size >= v.Len() {
			v.SetLen(size + 1)
		}
		st := reflect.New(typ)
		st = st.Elem()
		if q != nil {
			err := scanValue(rows, q, st)
			if err != nil {
				return err
			}
		} else {
			ti := newPtrInterface(typ)
			err := rows.Scan(ti)
			if err != nil {
				return err
			}
			setValue(st, ti)
		}
		v.Index(size).Set(st)
		size++
	}
	return nil
}
func convertAssignRow(i interface{}, row *sql.Row) error {
	typ := reflect.TypeOf(i)

	if typ.Kind() == reflect.Ptr && typ.Elem().Kind() != reflect.Struct {
		return row.Scan(i)
	}

	q, err := newTableSetter(reflect.ValueOf(i))
	if q == nil {
		return err
	}
	st := reflect.ValueOf(i).Elem()
	return scanValue(row, q, st)
}
<|endoftext|>


<commit_before>package semver

import (
	"fmt"
	"regexp"
	"strings"
)

// Version represents a SemVer 2.0.0 version and implements some high-level
// methods to manage multiple versions.
type SemVer struct {
	// The major version. This is an integer that increments when a backward-
	// incompatible change is made to a project's API.
	Major string

	// The minor version. Used to indicate feature addition.
	Minor string

	// The patch number. This is typically used to indicate bug fixes that
	// enhance existing functionality without changing or adding any API's.
	Patch string

	// The (optional) pre-release version from point 9 of semver 2.0.
	PreRel string

	// A string of optional build metadata per point 10 of semver 2.0.
	Build string
}

// String will return a flat string representing the semantic version
func (s *SemVer) String() string {
	res := fmt.Sprintf("%s.%s.%s", s.Major, s.Minor, s.Patch)
	if s.PreRel != "" {
		res = fmt.Sprintf("%s-%s", res, s.PreRel)
	}
	if s.Build != "" {
		res = fmt.Sprintf("%s+%s", res, s.Build)
	}
	return res
}

// parts will return all version components as a slice of strings.
func (s *SemVer) parts() []string {
	return []string{s.Major, s.Minor, s.Patch, s.PreRel, s.Build}
}

// New creates a new semver object from individual version components.
func New(major, minor, patch, preRel, build string) (*SemVer, error) {
	s := &SemVer{
		Major:  major,
		Minor:  minor,
		Patch:  patch,
		PreRel: preRel,
		Build:  build,
	}
	if err := s.verify(); err != nil {
		return nil, err
	}
	return s, nil
}

// New will create a new semantic versioning object from a flat
// string and populate all struct fields.
func NewFromString(vstr string) (*SemVer, error) {
	build := takeR(&vstr, "+")
	preRe := takeR(&vstr, "-")
	patch := takeR(&vstr, ".")
	minor := takeR(&vstr, ".")
	major := vstr
	return New(major, minor, patch, preRe, build)
}

// verify is used to ensure that a semver object complies with the format
// defined by semver.org.
func (s *SemVer) verify() error {
	baseRe, err := regexp.Compile("^[0-9]+$")
	extRe, err := regexp.Compile("^([0-9a-zA-Z-]+)?$")
	if err != nil {
		return err
	}

	if !(baseRe.MatchString(s.Major) && baseRe.MatchString(s.Minor) &&
		baseRe.MatchString(s.Patch) && extRe.MatchString(s.PreRel) &&
		extRe.MatchString(s.Build)) {

		return fmt.Errorf("semver: invalid version: %s", s.String())
	}

	return nil
}

// takeR will take all characters in a string from the right side of the subject
// until sep is encountered. The subject will be pruned in-place of both sep and
// the taken string. If sep is not present in subj, then "" is returned.
func takeR(subj *string, sep string) string {
	if !strings.Contains(*subj, sep) {
		return ""
	}
	parts := strings.Split(*subj, sep)
	l := len(parts)
	*subj = strings.Join(parts[0:l-1], sep)
	return parts[l-1]
}
<commit_msg>minor adjustment to trimR<commit_after>package semver

import (
	"fmt"
	"regexp"
	"strings"
)

// Version represents a SemVer 2.0.0 version and implements some high-level
// methods to manage multiple versions.
type SemVer struct {
	// The major version. This is an integer that increments when a backward-
	// incompatible change is made to a project's API.
	Major string

	// The minor version. Used to indicate feature addition.
	Minor string

	// The patch number. This is typically used to indicate bug fixes that
	// enhance existing functionality without changing or adding any API's.
	Patch string

	// The (optional) pre-release version from point 9 of semver 2.0.
	PreRel string

	// A string of optional build metadata per point 10 of semver 2.0.
	Build string
}

// String will return a flat string representing the semantic version
func (s *SemVer) String() string {
	res := fmt.Sprintf("%s.%s.%s", s.Major, s.Minor, s.Patch)
	if s.PreRel != "" {
		res = fmt.Sprintf("%s-%s", res, s.PreRel)
	}
	if s.Build != "" {
		res = fmt.Sprintf("%s+%s", res, s.Build)
	}
	return res
}

// parts will return all version components as a slice of strings.
func (s *SemVer) parts() []string {
	return []string{s.Major, s.Minor, s.Patch, s.PreRel, s.Build}
}

// New creates a new semver object from individual version components.
func New(major, minor, patch, preRel, build string) (*SemVer, error) {
	s := &SemVer{
		Major:  major,
		Minor:  minor,
		Patch:  patch,
		PreRel: preRel,
		Build:  build,
	}
	if err := s.verify(); err != nil {
		return nil, err
	}
	return s, nil
}

// New will create a new semantic versioning object from a flat
// string and populate all struct fields.
func NewFromString(vstr string) (*SemVer, error) {
	build := takeR(&vstr, "+")
	preRe := takeR(&vstr, "-")
	patch := takeR(&vstr, ".")
	minor := takeR(&vstr, ".")
	major := vstr
	return New(major, minor, patch, preRe, build)
}

// verify is used to ensure that a semver object complies with the format
// defined by semver.org.
func (s *SemVer) verify() error {
	baseRe, err := regexp.Compile("^[0-9]+$")
	extRe, err := regexp.Compile("^([0-9a-zA-Z-]+)?$")
	if err != nil {
		return err
	}

	if !(baseRe.MatchString(s.Major) && baseRe.MatchString(s.Minor) &&
		baseRe.MatchString(s.Patch) && extRe.MatchString(s.PreRel) &&
		extRe.MatchString(s.Build)) {

		return fmt.Errorf("semver: invalid version: %s", s.String())
	}

	return nil
}

// takeR will take all characters in a string from the right side of the subject
// until sep is encountered. The subject will be pruned in-place of both sep and
// the taken string. If sep is not present in subj, then "" is returned.
func takeR(subj *string, sep string) string {
	if !strings.Contains(*subj, sep) {
		return ""
	}
	parts := strings.Split(*subj, sep)
	last := len(parts) - 1
	*subj = strings.Join(parts[0:last], sep)
	return parts[last]
}
<|endoftext|>