<commit_before>package main

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"

	"github.com/mediocregopher/radix.v2/redis"
	"github.com/mtyurt/slack-bet/repo"
)

type DB struct {
	*sql.DB
}

const TimeFormat = "01-02-2006"

type Utility struct {
	RedisUrl string
}
type Utils interface {
	OpenRedis() (*redis.Client, error)
	PostHTTP(string, string) error
	GetAuthorizedUsers() []string
	GetChannelMembers() ([]string, error)
	GetRepo() repo.Repo
	GetConf() (*Conf, error)
	SendCallback(string)
}

func (util *Utility) GetRepo() repo.Repo {
	return nil
}
func (util *Utility) OpenRedis() (*redis.Client, error) {
	client, err := redis.Dial("tcp", util.RedisUrl)
	if err != nil {
		return nil, err
	}
	return client, nil
}
func (util *Utility) PostHTTP(url string, body string) error {
	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(body)))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	if _, err := client.Do(req); err != nil {
		return err
	}
	return nil
}

type Conf struct {
	Admins            []string `json:admins`
	Token             string   `json:readToken`
	Channel           string   `json:channel`
	ChannelID         string   `json:channelId`
	SlashCommandToken string   `json:slashCommandToken`
}

func (utils *Utility) SendCallback(text string) {
	conf, err := utils.GetConf()
	if err != nil {
		return
	}
	uri := "https://slack.com/api/chat.postMessage?token=" + conf.Token + "&channel=" + url.QueryEscape(conf.Channel) + "&text=" + url.QueryEscape(text) + "&as_user=true"
	resp, err := http.Get(uri)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer resp.Body.Close()
	_, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
func (util *Utility) GetAuthorizedUsers() []string {
	conf, err := util.GetConf()
	if err != nil {
		return []string{}
	}
	return conf.Admins
}
func (util *Utility) GetConf() (*Conf, error) {
	file, err := os.Open("conf.json")
	if err != nil {
		return nil, err
	}
	c := &Conf{}
	err = json.NewDecoder(file).Decode(c)
	if err != nil {
		return nil, err
	}
	return c, nil
}

type sluserinfo struct {
	Name    string `json:name`
	Deleted bool   `json:deleted`
}

type sluser struct {
	Ok   bool       `json:ok`
	User sluserinfo `json:user`
}

type slchannelinfo struct {
	Members []string `json:members`
}

type slchannel struct {
	Ok      bool          `json:ok`
	Channel slchannelinfo `json:channel`
}

func (util *Utility) GetChannelMembers() ([]string, error) {
	conf, err := util.GetConf()
	if err != nil {
		return nil, err
	}
	resp, err := http.Get("https://slack.com/api/channels.info?token=" + conf.Token + "&channel=" + conf.ChannelID)

	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, err
	}
	var channelInfo slchannel
	err = json.Unmarshal(body, &channelInfo)
	if err != nil {
		return nil, err
	}
	memberIds := channelInfo.Channel.Members
	var userNames []string
	baseUserInfoReqUrl := "https://slack.com/api/users.info?token=" + conf.Token + "&user="
	for _, userId := range memberIds {
		resp, err = http.Get(baseUserInfoReqUrl + userId)
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			return nil, err
		}
		var usrinfo sluser
		err = json.Unmarshal(body, &usrinfo)
		if err != nil {
			return nil, err
		}
		if usrinfo.User.Deleted {
			continue
		}
		userNames = append(userNames, usrinfo.User.Name)
	}
	return userNames, nil
}
<commit_msg>Read configuration only once and lazy-initialized<commit_after>package main

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"

	"github.com/mediocregopher/radix.v2/redis"
	"github.com/mtyurt/slack-bet/repo"
)

type DB struct {
	*sql.DB
}

const TimeFormat = "01-02-2006"

type Utility struct {
	RedisUrl string
	conf     *Conf
}
type Utils interface {
	OpenRedis() (*redis.Client, error)
	PostHTTP(string, string) error
	GetAuthorizedUsers() []string
	GetChannelMembers() ([]string, error)
	GetRepo() repo.Repo
	GetConf() (*Conf, error)
	SendCallback(string)
}

func (util *Utility) GetRepo() repo.Repo {
	return nil
}
func (util *Utility) OpenRedis() (*redis.Client, error) {
	client, err := redis.Dial("tcp", util.RedisUrl)
	if err != nil {
		return nil, err
	}
	return client, nil
}
func (util *Utility) PostHTTP(url string, body string) error {
	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(body)))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	if _, err := client.Do(req); err != nil {
		return err
	}
	return nil
}

type Conf struct {
	Admins            []string `json:admins`
	Token             string   `json:readToken`
	Channel           string   `json:channel`
	ChannelID         string   `json:channelId`
	SlashCommandToken string   `json:slashCommandToken`
}

func (utils *Utility) SendCallback(text string) {
	conf, err := utils.GetConf()
	if err != nil {
		return
	}
	uri := "https://slack.com/api/chat.postMessage?token=" + conf.Token + "&channel=" + url.QueryEscape(conf.Channel) + "&text=" + url.QueryEscape(text) + "&as_user=true"
	resp, err := http.Get(uri)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer resp.Body.Close()
	_, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
func (util *Utility) GetAuthorizedUsers() []string {
	conf, err := util.GetConf()
	if err != nil {
		return []string{}
	}
	return conf.Admins
}
func (util *Utility) GetConf() (*Conf, error) {
	if util.conf != nil {
		return util.conf, nil
	}
	file, err := os.Open("conf.json")
	if err != nil {
		return nil, err
	}
	c := &Conf{}
	err = json.NewDecoder(file).Decode(c)
	if err != nil {
		return nil, err
	}
	util.conf = c
	return c, nil
}

type sluserinfo struct {
	Name    string `json:name`
	Deleted bool   `json:deleted`
}

type sluser struct {
	Ok   bool       `json:ok`
	User sluserinfo `json:user`
}

type slchannelinfo struct {
	Members []string `json:members`
}

type slchannel struct {
	Ok      bool          `json:ok`
	Channel slchannelinfo `json:channel`
}

func (util *Utility) GetChannelMembers() ([]string, error) {
	conf, err := util.GetConf()
	if err != nil {
		return nil, err
	}
	resp, err := http.Get("https://slack.com/api/channels.info?token=" + conf.Token + "&channel=" + conf.ChannelID)

	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, err
	}
	var channelInfo slchannel
	err = json.Unmarshal(body, &channelInfo)
	if err != nil {
		return nil, err
	}
	memberIds := channelInfo.Channel.Members
	var userNames []string
	baseUserInfoReqUrl := "https://slack.com/api/users.info?token=" + conf.Token + "&user="
	for _, userId := range memberIds {
		resp, err = http.Get(baseUserInfoReqUrl + userId)
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			return nil, err
		}
		var usrinfo sluser
		err = json.Unmarshal(body, &usrinfo)
		if err != nil {
			return nil, err
		}
		if usrinfo.User.Deleted {
			continue
		}
		userNames = append(userNames, usrinfo.User.Name)
	}
	return userNames, nil
}
<|endoftext|>


<commit_before>// (c) 2012 Alexander Solovyov
// under terms of ISC license

package main

import (
	"fmt"
	bf "github.com/russross/blackfriday"
	"io"
	"os"
	"strings"
	"unicode"
)

func errhandle(err error) {
	if err == nil {
		return
	}
	fmt.Printf("Error: %s\n", err)
}

func out(format string, args ...interface{}) {
	fmt.Printf(format, args...)
}

func debug(format string, args ...interface{}) {
	if !opts.Verbose {
		return
	}
	fmt.Printf(format, args...)
}

func SliceStringIndexOf(haystack []string, needle string) int {
	for i, elem := range haystack {
		if elem == needle {
			return i
		}
	}
	return -1
}

func Markdown(source string) string {
	// set up the HTML renderer
	flags := 0
	flags |= bf.HTML_USE_SMARTYPANTS
	flags |= bf.HTML_SMARTYPANTS_FRACTIONS
	renderer := bf.HtmlRenderer(flags, "", "")

	// set up the parser
	ext := 0
	ext |= bf.EXTENSION_NO_INTRA_EMPHASIS
	ext |= bf.EXTENSION_TABLES
	ext |= bf.EXTENSION_FENCED_CODE
	ext |= bf.EXTENSION_AUTOLINK
	ext |= bf.EXTENSION_STRIKETHROUGH
	ext |= bf.EXTENSION_SPACE_HEADERS

	return string(bf.Markdown([]byte(source), renderer, ext))
}

func TrimSplitN(s string, sep string, n int) []string {
	bits := strings.SplitN(s, sep, n)
	for i, bit := range bits {
		bits[i] = strings.TrimSpace(bit)
	}
	return bits
}

func NonEmptySplit(s string, sep string) []string {
	bits := strings.Split(s, sep)
	out := make([]string, 0)
	for _, x := range bits {
		if len(x) != 0 {
			out = append(out, x)
		}
	}
	return out
}

func Capitalize(s string) string {
	return strings.ToUpper(s[0:1]) + strings.Map(unicode.ToLower, s[1:])
}

func CopyFile(srcPath, dstPath string) (n int64, err error) {
	fstat, err := os.Lstat(srcPath)

	if fstat.Mode()&os.ModeSymlink != 0 {
		target, err := os.Readlink(srcPath)
		if err != nil {
			return 0, err
		}

		err = os.Symlink(target, dstPath)
		if err != nil {
			return 0, err
		}

		return 1, nil
	}

	src, err := os.Open(srcPath)
	if err != nil {
		return 0, err
	}
	defer src.Close()

	dst, err := os.Create(dstPath)
	if err != nil {
		return 0, err
	}
	defer dst.Close()

	n, err = io.Copy(dst, src)
	return n, err
}
<commit_msg>Markdown: Enable EXTENSION_FOOTNOTES<commit_after>// (c) 2012 Alexander Solovyov
// under terms of ISC license

package main

import (
	"fmt"
	bf "github.com/russross/blackfriday"
	"io"
	"os"
	"strings"
	"unicode"
)

func errhandle(err error) {
	if err == nil {
		return
	}
	fmt.Printf("Error: %s\n", err)
}

func out(format string, args ...interface{}) {
	fmt.Printf(format, args...)
}

func debug(format string, args ...interface{}) {
	if !opts.Verbose {
		return
	}
	fmt.Printf(format, args...)
}

func SliceStringIndexOf(haystack []string, needle string) int {
	for i, elem := range haystack {
		if elem == needle {
			return i
		}
	}
	return -1
}

func Markdown(source string) string {
	// set up the HTML renderer
	flags := 0
	flags |= bf.HTML_USE_SMARTYPANTS
	flags |= bf.HTML_SMARTYPANTS_FRACTIONS
	renderer := bf.HtmlRenderer(flags, "", "")

	// set up the parser
	ext := 0
	ext |= bf.EXTENSION_NO_INTRA_EMPHASIS
	ext |= bf.EXTENSION_TABLES
	ext |= bf.EXTENSION_FENCED_CODE
	ext |= bf.EXTENSION_AUTOLINK
	ext |= bf.EXTENSION_STRIKETHROUGH
	ext |= bf.EXTENSION_SPACE_HEADERS
	ext |= bf.EXTENSION_FOOTNOTES

	return string(bf.Markdown([]byte(source), renderer, ext))
}

func TrimSplitN(s string, sep string, n int) []string {
	bits := strings.SplitN(s, sep, n)
	for i, bit := range bits {
		bits[i] = strings.TrimSpace(bit)
	}
	return bits
}

func NonEmptySplit(s string, sep string) []string {
	bits := strings.Split(s, sep)
	out := make([]string, 0)
	for _, x := range bits {
		if len(x) != 0 {
			out = append(out, x)
		}
	}
	return out
}

func Capitalize(s string) string {
	return strings.ToUpper(s[0:1]) + strings.Map(unicode.ToLower, s[1:])
}

func CopyFile(srcPath, dstPath string) (n int64, err error) {
	fstat, err := os.Lstat(srcPath)

	if fstat.Mode()&os.ModeSymlink != 0 {
		target, err := os.Readlink(srcPath)
		if err != nil {
			return 0, err
		}

		err = os.Symlink(target, dstPath)
		if err != nil {
			return 0, err
		}

		return 1, nil
	}

	src, err := os.Open(srcPath)
	if err != nil {
		return 0, err
	}
	defer src.Close()

	dst, err := os.Create(dstPath)
	if err != nil {
		return 0, err
	}
	defer dst.Close()

	n, err = io.Copy(dst, src)
	return n, err
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
)

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

// Capitalize a string or return the same if it is too short
func capitalize(s string) string {
	switch {
	case len(s) >= 2:
		return strings.ToTitle(s[0:1]) + s[1:]
	case len(s) == 1:
		return strings.ToUpper(string(s[0]))
	default:
		return s
	}
}

// Return what's between two strings, "a" and "b", in another string
func between(orig string, a string, b string) string {
	if strings.Contains(orig, a) && strings.Contains(orig, b) {
		posa := strings.Index(orig, a) + len(a)
		posb := strings.LastIndex(orig, b)
		if posa > posb {
			return ""
		}
		return orig[posa:posb]
	}
	return ""
}

// Return the contents between "" or '' (or an empty string)
func betweenQuotes(orig string) string {
	var s string
	for _, quote := range []string{"\"", "'"} {
		s = between(orig, quote, quote)
		if s != "" {
			return s
		}
	}
	return ""
}

// Return the string between the quotes or after the "=", if possible
// or return the original string
func betweenQuotesOrAfterEquals(orig string) string {
	s := betweenQuotes(orig)
	// Check for exactly one "="
	if s == "" && strings.Count(orig, "=") == 1 {
		s = strings.TrimSpace(strings.Split(orig, "=")[1])
	}
	return s
}

// Does a keyword exist in the string?
// Disregards several common special characters (like -, _ and .)
func has(s string, kw string) bool {
	var (
		lowercase = strings.ToLower(s)
		// Remove the most common special characters
		massaged = strings.Trim(lowercase, "-_.,!?()[]{}\\/:;+@")
		words    = strings.Split(massaged, " ")
	)
	for _, word := range words {
		if word == kw {
			return true
		}
	}
	return false
}
<commit_msg>Add a utility function<commit_after>package main

import (
	"os"
	"strings"
)

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

// Capitalize a string or return the same if it is too short
func capitalize(s string) string {
	switch {
	case len(s) >= 2:
		return strings.ToTitle(s[0:1]) + s[1:]
	case len(s) == 1:
		return strings.ToUpper(string(s[0]))
	default:
		return s
	}
}

// Return what's between two strings, "a" and "b", in another string
func between(orig string, a string, b string) string {
	if strings.Contains(orig, a) && strings.Contains(orig, b) {
		posa := strings.Index(orig, a) + len(a)
		posb := strings.LastIndex(orig, b)
		if posa > posb {
			return ""
		}
		return orig[posa:posb]
	}
	return ""
}

// Return the contents between "" or '' (or an empty string)
func betweenQuotes(orig string) string {
	var s string
	for _, quote := range []string{"\"", "'"} {
		s = between(orig, quote, quote)
		if s != "" {
			return s
		}
	}
	return ""
}

// Return the string between the quotes or after the "=", if possible
// or return the original string
func betweenQuotesOrAfterEquals(orig string) string {
	s := betweenQuotes(orig)
	// Check for exactly one "="
	if s == "" && strings.Count(orig, "=") == 1 {
		s = strings.TrimSpace(strings.Split(orig, "=")[1])
	}
	return s
}

// Does a keyword exist in the string?
// Disregards several common special characters (like -, _ and .)
func has(s string, kw string) bool {
	var (
		lowercase = strings.ToLower(s)
		// Remove the most common special characters
		massaged = strings.Trim(lowercase, "-_.,!?()[]{}\\/:;+@")
		words    = strings.Split(massaged, " ")
	)
	for _, word := range words {
		if word == kw {
			return true
		}
	}
	return false
}

// exists checks if the given path exists
func exists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 xgfone

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 config

import (
	"fmt"
	"html/template"
	"reflect"
	"strconv"
	"strings"
)

func inMap(m map[string]interface{}, key string) bool {
	_, ok := m[key]
	return ok
}

// IsZero returns true if the value is ZERO, or false.
func IsZero(v interface{}) bool {
	ok, _ := template.IsTrue(v)
	return !ok
}

// bool2Int converts the bool to int64.
func bool2Int(b bool) int64 {
	if b {
		return 1
	}
	return 0
}

// ToBool does the best to convert a certain value to bool
//
// For "t", "T", "1", "true", "True", "TRUE", it's true.
// For "f", "F", "0", "false", "False", "FALSE", it's false.
func ToBool(v interface{}) (bool, error) {
	switch v.(type) {
	case string:
		_v := v.(string)
		switch _v {
		case "t", "T", "1", "true", "True", "TRUE":
			return true, nil
		case "f", "F", "0", "false", "False", "FALSE", "":
			return false, nil
		default:
			return false, fmt.Errorf("unrecognized bool string: %s", _v)
		}
	}
	return !IsZero(v), nil
}

// ToInt64 does the best to convert a certain value to int64.
func ToInt64(_v interface{}) (v int64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = int64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = int64(bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Int()
	case uint, uint8, uint16, uint32, uint64:
		v = int64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = int64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseInt(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToUint64 does the best to convert a certain value to uint64.
func ToUint64(_v interface{}) (v uint64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = uint64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = uint64(bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Uint()
	case uint, uint8, uint16, uint32, uint64:
		v = uint64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = uint64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseUint(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToFloat64 does the best to convert a certain value to float64.
func ToFloat64(_v interface{}) (v float64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = float64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = float64(bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = float64(reflect.ValueOf(_v).Int())
	case uint, uint8, uint16, uint32, uint64:
		v = float64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = reflect.ValueOf(_v).Float()
	case string:
		return strconv.ParseFloat(_v.(string), 64)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToString does the best to convert a certain value to string.
func ToString(_v interface{}) (v string, err error) {
	switch _v.(type) {
	case string:
		v = _v.(string)
	case []byte:
		v = string(_v.([]byte))
	case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32,
		uint64:
		v = fmt.Sprintf("%d", _v)
	case float32, float64:
		v = fmt.Sprintf("%f", _v)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToStringSlice does the best to convert a certain value to []string.
func ToStringSlice(_v interface{}) (v []string, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]string, 0, len(vs))
		for _, s := range vs {
			s = strings.TrimSpace(s)
			if s != "" {
				v = append(v, s)
			}
		}
	case []string:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToIntSlice does the best to convert a certain value to []int.
func ToIntSlice(_v interface{}) (v []int, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]int, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToInt64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, int(i))
		}
	case []int:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToInt64Slice does the best to convert a certain value to []int64.
func ToInt64Slice(_v interface{}) (v []int64, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]int64, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToInt64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, i)
		}
	case []int64:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToUintSlice does the best to convert a certain value to []uint.
func ToUintSlice(_v interface{}) (v []uint, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]uint, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToUint64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, uint(i))
		}
	case []uint:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToUint64Slice does the best to convert a certain value to []uint64.
func ToUint64Slice(_v interface{}) (v []uint64, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]uint64, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToUint64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, i)
		}
	case []uint64:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToFloat64Slice does the best to convert a certain value to []float64.
func ToFloat64Slice(_v interface{}) (v []float64, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]float64, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToFloat64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, i)
		}
	case []float64:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}
<commit_msg>Parse on/On/ON/off/Off/OFF as the string bool<commit_after>/*
Copyright 2017 xgfone

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 config

import (
	"fmt"
	"html/template"
	"reflect"
	"strconv"
	"strings"
)

func inMap(m map[string]interface{}, key string) bool {
	_, ok := m[key]
	return ok
}

// IsZero returns true if the value is ZERO, or false.
func IsZero(v interface{}) bool {
	ok, _ := template.IsTrue(v)
	return !ok
}

// bool2Int converts the bool to int64.
func bool2Int(b bool) int64 {
	if b {
		return 1
	}
	return 0
}

// ToBool does the best to convert a certain value to bool
//
// For "t", "T", "1", "true", "True", "TRUE", it's true.
// For "f", "F", "0", "false", "False", "FALSE", it's false.
func ToBool(v interface{}) (bool, error) {
	switch v.(type) {
	case string:
		_v := v.(string)
		switch _v {
		case "t", "T", "1", "on", "On", "ON", "true", "True", "TRUE":
			return true, nil
		case "f", "F", "0", "off", "Off", "OFF", "false", "False", "FALSE", "":
			return false, nil
		default:
			return false, fmt.Errorf("unrecognized bool string: %s", _v)
		}
	}
	return !IsZero(v), nil
}

// ToInt64 does the best to convert a certain value to int64.
func ToInt64(_v interface{}) (v int64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = int64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = int64(bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Int()
	case uint, uint8, uint16, uint32, uint64:
		v = int64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = int64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseInt(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToUint64 does the best to convert a certain value to uint64.
func ToUint64(_v interface{}) (v uint64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = uint64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = uint64(bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Uint()
	case uint, uint8, uint16, uint32, uint64:
		v = uint64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = uint64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseUint(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToFloat64 does the best to convert a certain value to float64.
func ToFloat64(_v interface{}) (v float64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = float64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = float64(bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = float64(reflect.ValueOf(_v).Int())
	case uint, uint8, uint16, uint32, uint64:
		v = float64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = reflect.ValueOf(_v).Float()
	case string:
		return strconv.ParseFloat(_v.(string), 64)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToString does the best to convert a certain value to string.
func ToString(_v interface{}) (v string, err error) {
	switch _v.(type) {
	case string:
		v = _v.(string)
	case []byte:
		v = string(_v.([]byte))
	case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32,
		uint64:
		v = fmt.Sprintf("%d", _v)
	case float32, float64:
		v = fmt.Sprintf("%f", _v)
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToStringSlice does the best to convert a certain value to []string.
func ToStringSlice(_v interface{}) (v []string, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]string, 0, len(vs))
		for _, s := range vs {
			s = strings.TrimSpace(s)
			if s != "" {
				v = append(v, s)
			}
		}
	case []string:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToIntSlice does the best to convert a certain value to []int.
func ToIntSlice(_v interface{}) (v []int, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]int, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToInt64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, int(i))
		}
	case []int:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToInt64Slice does the best to convert a certain value to []int64.
func ToInt64Slice(_v interface{}) (v []int64, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]int64, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToInt64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, i)
		}
	case []int64:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToUintSlice does the best to convert a certain value to []uint.
func ToUintSlice(_v interface{}) (v []uint, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]uint, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToUint64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, uint(i))
		}
	case []uint:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToUint64Slice does the best to convert a certain value to []uint64.
func ToUint64Slice(_v interface{}) (v []uint64, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]uint64, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToUint64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, i)
		}
	case []uint64:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}

// ToFloat64Slice does the best to convert a certain value to []float64.
func ToFloat64Slice(_v interface{}) (v []float64, err error) {
	switch vv := _v.(type) {
	case string:
		vs := strings.Split(vv, ",")
		v = make([]float64, 0, len(vs))
		for _, s := range vs {
			if s = strings.TrimSpace(s); s == "" {
				continue
			}

			i, err := ToFloat64(s)
			if err != nil {
				return nil, err
			}
			v = append(v, i)
		}
	case []float64:
		v = vv
	default:
		err = fmt.Errorf("unknown type of %T", _v)
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2015 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

package isolate

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"github.com/luci/luci-go/client/archiver"
	"github.com/luci/luci-go/client/internal/common"
	"github.com/luci/luci-go/common/flag/stringmapflag"
	"github.com/luci/luci-go/common/isolated"
	"github.com/luci/luci-go/common/isolatedclient"
	"github.com/luci/luci-go/common/runtime/tracer"
)

// IsolatedGenJSONVersion is used in the batcharchive json format.
//
// TODO(tandrii): Migrate to batch_archive.go.
const IsolatedGenJSONVersion = 1

// ValidVariable is the regexp of valid isolate variable name.
const ValidVariable = "[A-Za-z_][A-Za-z_0-9]*"

var validVariableMatcher = regexp.MustCompile(ValidVariable)
var variableSubstitutionMatcher = regexp.MustCompile("<\\(" + ValidVariable + "\\)")

// IsValidVariable returns true if the variable is a valid symbol name.
func IsValidVariable(variable string) bool {
	return validVariableMatcher.MatchString(variable)
}

// Tree to be isolated.
type Tree struct {
	Cwd  string
	Opts ArchiveOptions
}

// ArchiveOptions for achiving trees.
type ArchiveOptions struct {
	Isolate         string              `json:"isolate"`
	Isolated        string              `json:"isolated"`
	Blacklist       common.Strings      `json:"blacklist"`
	PathVariables   stringmapflag.Value `json:"path_variables"`
	ExtraVariables  stringmapflag.Value `json:"extra_variables"`
	ConfigVariables stringmapflag.Value `json:"config_variables"`
}

// Init initializes with non-nil values.
func (a *ArchiveOptions) Init() {
	a.Blacklist = common.Strings{}
	a.PathVariables = map[string]string{}
	if common.IsWindows() {
		a.PathVariables["EXECUTABLE_SUFFIX"] = ".exe"
	} else {
		a.PathVariables["EXECUTABLE_SUFFIX"] = ""
	}
	a.ExtraVariables = map[string]string{}
	a.ConfigVariables = map[string]string{}
}

// PostProcess post-processes the flags to fix any compatibility issue.
func (a *ArchiveOptions) PostProcess(cwd string) {
	// Set default blacklist only if none is set.
	if len(a.Blacklist) == 0 {
		// This cannot be generalized as ".*" as there is known use that require
		// a ".pki" directory to be mapped.
		a.Blacklist = common.Strings{
			// Temporary python files.
			"*.pyc",
			// Temporary vim files.
			"*.swp",
			".git",
			".hg",
			".svn",
		}
	}
	if !filepath.IsAbs(a.Isolate) {
		a.Isolate = filepath.Join(cwd, a.Isolate)
	}
	a.Isolate = filepath.Clean(a.Isolate)

	if !filepath.IsAbs(a.Isolated) {
		a.Isolated = filepath.Join(cwd, a.Isolated)
	}
	a.Isolated = filepath.Clean(a.Isolated)

	for k, v := range a.PathVariables {
		// This is due to a Windows + GYP specific issue, where double-quoted paths
		// would get mangled in a way that cannot be resolved unless a space is
		// injected.
		a.PathVariables[k] = strings.TrimSpace(v)
	}
}

// ReplaceVariables replaces any occurrences of '<(FOO)' in 'str' with the
// corresponding variable from 'opts'.
//
// If any substitution refers to a variable that is missing, the returned error will
// refer to the first such variable. In the case of errors, the returned string will
// still contain a valid result for any non-missing substitutions.
func ReplaceVariables(str string, opts *ArchiveOptions) (string, error) {
	var err error
	subst := variableSubstitutionMatcher.ReplaceAllStringFunc(str,
		func(match string) string {
			varName := match[2 : len(match)-1]
			if v, ok := opts.PathVariables[varName]; ok {
				return v
			}
			if v, ok := opts.ExtraVariables[varName]; ok {
				return v
			}
			if v, ok := opts.ConfigVariables[varName]; ok {
				return v
			}
			if err == nil {
				err = errors.New("no value for variable '" + varName + "'")
			}
			return match
		})
	return subst, err
}

// Archive processes a .isolate, generates a .isolated and archive it.
// Returns a *Item to the .isolated.
func Archive(arch *archiver.Archiver, opts *ArchiveOptions) *archiver.Item {
	displayName := filepath.Base(opts.Isolated)
	defer tracer.Span(arch, strings.SplitN(displayName, ".", 2)[0]+":archive", nil)(nil)
	f, err := archive(arch, opts, displayName)
	if err != nil {
		arch.Cancel(err)
		i := &archiver.Item{DisplayName: displayName}
		i.SetErr(err)
		return i
	}
	return f
}

func processing(opts *ArchiveOptions) (int, int, []string, string, *isolated.Isolated, error) {
	content, err := ioutil.ReadFile(opts.Isolate)
	if err != nil {
		return 0, 0, nil, "", nil, err
	}
	cmd, deps, readOnly, isolateDir, err := LoadIsolateForConfig(filepath.Dir(opts.Isolate), content, opts.ConfigVariables)
	if err != nil {
		return 0, 0, nil, "", nil, err
	}

	// Check for variable error before doing anything.
	for i := range cmd {
		if cmd[i], err = ReplaceVariables(cmd[i], opts); err != nil {
			return 0, 0, nil, "", nil, err
		}
	}
	filesCount := 0
	dirsCount := 0
	for i := range deps {
		if deps[i], err = ReplaceVariables(deps[i], opts); err != nil {
			return 0, 0, nil, "", nil, err
		}
		if deps[i][len(deps[i])-1] == os.PathSeparator {
			dirsCount++
		} else {
			filesCount++
		}
	}

	// Convert all dependencies to absolute path and find the root directory to
	// use.
	for i, dep := range deps {
		clean := filepath.Clean(filepath.Join(isolateDir, dep))
		if dep[len(dep)-1] == os.PathSeparator {
			clean += osPathSeparator
		}
		deps[i] = clean
	}
	rootDir := isolateDir
	for _, dep := range deps {
		base := filepath.Dir(dep)
		for {
			rel, err := filepath.Rel(rootDir, base)
			if err != nil {
				return 0, 0, nil, "", nil, err
			}
			if !strings.HasPrefix(rel, "..") {
				break
			}
			newRootDir := filepath.Dir(rootDir)
			if newRootDir == rootDir {
				return 0, 0, nil, "", nil, errors.New("failed to find root dir")
			}
			rootDir = newRootDir
		}
	}
	if rootDir != isolateDir {
		log.Printf("Root: %s", rootDir)
	}

	// Prepare the .isolated file.
	i := &isolated.Isolated{
		Algo:     "sha-1",
		Files:    map[string]isolated.File{},
		ReadOnly: readOnly.ToIsolated(),
		Version:  isolated.IsolatedFormatVersion,
	}
	if len(cmd) != 0 {
		i.Command = cmd
	}
	if rootDir != isolateDir {
		relPath, err := filepath.Rel(rootDir, isolateDir)
		if err != nil {
			return 0, 0, nil, "", nil, err
		}
		i.RelativeCwd = relPath
	}
	// Processing of the .isolate file ended.
	return filesCount, dirsCount, deps, rootDir, i, err
}

func archive(arch *archiver.Archiver, opts *ArchiveOptions, displayName string) (*archiver.Item, error) {
	end := tracer.Span(arch, strings.SplitN(displayName, ".", 2)[0]+":loading", nil)
	filesCount, dirsCount, deps, rootDir, i, err := processing(opts)
	end(tracer.Args{"err": err})
	if err != nil {
		return nil, err
	}
	// Handle each dependency, either a file or a directory..
	fileItems := make([]*archiver.Item, 0, filesCount)
	dirItems := make([]*archiver.Item, 0, dirsCount)
	for _, dep := range deps {
		relPath, err := filepath.Rel(rootDir, dep)
		if err != nil {
			return nil, err
		}
		if dep[len(dep)-1] == os.PathSeparator {
			relPath, err := filepath.Rel(rootDir, dep)
			if err != nil {
				return nil, err
			}
			dirItems = append(dirItems, archiver.PushDirectory(arch, dep, relPath, opts.Blacklist))
		} else {
			// Grab the stats right away.
			info, err := os.Lstat(dep)
			if err != nil {
				return nil, err
			}
			mode := info.Mode()
			if mode&os.ModeSymlink == os.ModeSymlink {
				l, err := os.Readlink(dep)
				if err != nil {
					return nil, err
				}
				i.Files[relPath] = isolated.File{Link: newString(l)}
			} else {
				i.Files[relPath] = isolated.File{Mode: newInt(int(mode.Perm())), Size: newInt64(info.Size())}
				fileItems = append(fileItems, arch.PushFile(relPath, dep, -info.Size()))
			}
		}
	}

	for _, item := range fileItems {
		item.WaitForHashed()
		if err = item.Error(); err != nil {
			return nil, err
		}
		f := i.Files[item.DisplayName]
		f.Digest = item.Digest()
		i.Files[item.DisplayName] = f
	}
	// Avoid duplicated entries in includes.
	// TODO(tandrii): add test to reproduce the problem.
	includesSet := map[isolated.HexDigest]bool{}
	for _, item := range dirItems {
		item.WaitForHashed()
		if err = item.Error(); err != nil {
			return nil, err
		}
		includesSet[item.Digest()] = true
	}
	for digest := range includesSet {
		i.Includes = append(i.Includes, digest)
	}
	// Make the includes list deterministic.
	sort.Sort(i.Includes)

	raw := &bytes.Buffer{}
	if err = json.NewEncoder(raw).Encode(i); err != nil {
		return nil, err
	}

	if err := ioutil.WriteFile(opts.Isolated, raw.Bytes(), 0644); err != nil {
		return nil, err
	}
	return arch.Push(displayName, isolatedclient.NewBytesSource(raw.Bytes()), 0), nil
}
<commit_msg>client/isolate: factor-out isolate file parsing<commit_after>// Copyright 2015 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

package isolate

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"github.com/luci/luci-go/client/archiver"
	"github.com/luci/luci-go/client/internal/common"
	"github.com/luci/luci-go/common/flag/stringmapflag"
	"github.com/luci/luci-go/common/isolated"
	"github.com/luci/luci-go/common/isolatedclient"
	"github.com/luci/luci-go/common/runtime/tracer"
)

// IsolatedGenJSONVersion is used in the batcharchive json format.
//
// TODO(tandrii): Migrate to batch_archive.go.
const IsolatedGenJSONVersion = 1

// ValidVariable is the regexp of valid isolate variable name.
const ValidVariable = "[A-Za-z_][A-Za-z_0-9]*"

var validVariableMatcher = regexp.MustCompile(ValidVariable)
var variableSubstitutionMatcher = regexp.MustCompile("<\\(" + ValidVariable + "\\)")

// IsValidVariable returns true if the variable is a valid symbol name.
func IsValidVariable(variable string) bool {
	return validVariableMatcher.MatchString(variable)
}

// Tree to be isolated.
type Tree struct {
	Cwd  string
	Opts ArchiveOptions
}

// ArchiveOptions for achiving trees.
type ArchiveOptions struct {
	Isolate         string              `json:"isolate"`
	Isolated        string              `json:"isolated"`
	Blacklist       common.Strings      `json:"blacklist"`
	PathVariables   stringmapflag.Value `json:"path_variables"`
	ExtraVariables  stringmapflag.Value `json:"extra_variables"`
	ConfigVariables stringmapflag.Value `json:"config_variables"`
}

// Init initializes with non-nil values.
func (a *ArchiveOptions) Init() {
	a.Blacklist = common.Strings{}
	a.PathVariables = map[string]string{}
	if common.IsWindows() {
		a.PathVariables["EXECUTABLE_SUFFIX"] = ".exe"
	} else {
		a.PathVariables["EXECUTABLE_SUFFIX"] = ""
	}
	a.ExtraVariables = map[string]string{}
	a.ConfigVariables = map[string]string{}
}

// PostProcess post-processes the flags to fix any compatibility issue.
func (a *ArchiveOptions) PostProcess(cwd string) {
	// Set default blacklist only if none is set.
	if len(a.Blacklist) == 0 {
		// This cannot be generalized as ".*" as there is known use that require
		// a ".pki" directory to be mapped.
		a.Blacklist = common.Strings{
			// Temporary python files.
			"*.pyc",
			// Temporary vim files.
			"*.swp",
			".git",
			".hg",
			".svn",
		}
	}
	if !filepath.IsAbs(a.Isolate) {
		a.Isolate = filepath.Join(cwd, a.Isolate)
	}
	a.Isolate = filepath.Clean(a.Isolate)

	if !filepath.IsAbs(a.Isolated) {
		a.Isolated = filepath.Join(cwd, a.Isolated)
	}
	a.Isolated = filepath.Clean(a.Isolated)

	for k, v := range a.PathVariables {
		// This is due to a Windows + GYP specific issue, where double-quoted paths
		// would get mangled in a way that cannot be resolved unless a space is
		// injected.
		a.PathVariables[k] = strings.TrimSpace(v)
	}
}

// ReplaceVariables replaces any occurrences of '<(FOO)' in 'str' with the
// corresponding variable from 'opts'.
//
// If any substitution refers to a variable that is missing, the returned error will
// refer to the first such variable. In the case of errors, the returned string will
// still contain a valid result for any non-missing substitutions.
func ReplaceVariables(str string, opts *ArchiveOptions) (string, error) {
	var err error
	subst := variableSubstitutionMatcher.ReplaceAllStringFunc(str,
		func(match string) string {
			varName := match[2 : len(match)-1]
			if v, ok := opts.PathVariables[varName]; ok {
				return v
			}
			if v, ok := opts.ExtraVariables[varName]; ok {
				return v
			}
			if v, ok := opts.ConfigVariables[varName]; ok {
				return v
			}
			if err == nil {
				err = errors.New("no value for variable '" + varName + "'")
			}
			return match
		})
	return subst, err
}

// Archive processes a .isolate, generates a .isolated and archive it.
// Returns a *Item to the .isolated.
func Archive(arch *archiver.Archiver, opts *ArchiveOptions) *archiver.Item {
	displayName := filepath.Base(opts.Isolated)
	defer tracer.Span(arch, strings.SplitN(displayName, ".", 2)[0]+":archive", nil)(nil)
	f, err := archive(arch, opts, displayName)
	if err != nil {
		arch.Cancel(err)
		i := &archiver.Item{DisplayName: displayName}
		i.SetErr(err)
		return i
	}
	return f
}

// ProcessIsolate parses an isolate file, returning the list of dependencies
// (both files and directories), the root directory and the initial Isolated struct.
func ProcessIsolate(opts *ArchiveOptions) ([]string, string, *isolated.Isolated, error) {
	content, err := ioutil.ReadFile(opts.Isolate)
	if err != nil {
		return nil, "", nil, err
	}
	cmd, deps, readOnly, isolateDir, err := LoadIsolateForConfig(filepath.Dir(opts.Isolate), content, opts.ConfigVariables)
	if err != nil {
		return nil, "", nil, err
	}

	// Expand variables in the commands.
	for i := range cmd {
		if cmd[i], err = ReplaceVariables(cmd[i], opts); err != nil {
			return nil, "", nil, err
		}
	}

	// Expand variables in the deps, and convert each path to a cleaned absolute form.
	for i := range deps {
		dep, err := ReplaceVariables(deps[i], opts)
		if err != nil {
			return nil, "", nil, err
		}
		deps[i] = join(isolateDir, dep)
	}

	// Find the root directory of all the files (the root might be above isolateDir).
	rootDir := isolateDir
	for _, dep := range deps {
		// Check if the dep is outside isolateDir.
		base := filepath.Dir(dep)
		for {
			rel, err := filepath.Rel(rootDir, base)
			if err != nil {
				return nil, "", nil, err
			}
			if !strings.HasPrefix(rel, "..") {
				break
			}
			newRootDir := filepath.Dir(rootDir)
			if newRootDir == rootDir {
				return nil, "", nil, errors.New("failed to find root dir")
			}
			rootDir = newRootDir
		}
	}
	if rootDir != isolateDir {
		log.Printf("Root: %s", rootDir)
	}

	// Prepare the .isolated struct.
	isol := &isolated.Isolated{
		Algo:     "sha-1",
		Files:    map[string]isolated.File{},
		ReadOnly: readOnly.ToIsolated(),
		Version:  isolated.IsolatedFormatVersion,
	}
	if len(cmd) != 0 {
		isol.Command = cmd
	}
	if rootDir != isolateDir {
		relPath, err := filepath.Rel(rootDir, isolateDir)
		if err != nil {
			return nil, "", nil, err
		}
		isol.RelativeCwd = relPath
	}
	return deps, rootDir, isol, nil
}

func processing(opts *ArchiveOptions) (filesCount, dirsCount int, deps []string, rootDir string, isol *isolated.Isolated, err error) {
	deps, rootDir, isol, err = ProcessIsolate(opts)
	if err != nil {
		return 0, 0, nil, "", nil, err
	}

	for i := range deps {
		if deps[i][len(deps[i])-1] == os.PathSeparator {
			dirsCount++
		} else {
			filesCount++
		}
	}

	// Processing of the .isolate file ended.
	return filesCount, dirsCount, deps, rootDir, isol, nil
}

// join joins the provided pair of path elements. Unlike filepath.Join, join
// will preserve the trailing slash of the second element, if any.
// TODO(djd): delete this function. Preserving the slash is fragile, and we
// can tell if a path is a dir by stat'ing it (which we need to do anyway).
func join(p1, p2 string) string {
	joined := filepath.Join(p1, p2)
	if p2[len(p2)-1] == os.PathSeparator {
		joined += osPathSeparator // Retain trailing slash.
	}
	return joined
}

func archive(arch *archiver.Archiver, opts *ArchiveOptions, displayName string) (*archiver.Item, error) {
	end := tracer.Span(arch, strings.SplitN(displayName, ".", 2)[0]+":loading", nil)
	filesCount, dirsCount, deps, rootDir, i, err := processing(opts)
	end(tracer.Args{"err": err})
	if err != nil {
		return nil, err
	}
	// Handle each dependency, either a file or a directory..
	fileItems := make([]*archiver.Item, 0, filesCount)
	dirItems := make([]*archiver.Item, 0, dirsCount)
	for _, dep := range deps {
		relPath, err := filepath.Rel(rootDir, dep)
		if err != nil {
			return nil, err
		}
		if dep[len(dep)-1] == os.PathSeparator {
			relPath, err := filepath.Rel(rootDir, dep)
			if err != nil {
				return nil, err
			}
			dirItems = append(dirItems, archiver.PushDirectory(arch, dep, relPath, opts.Blacklist))
		} else {
			// Grab the stats right away.
			info, err := os.Lstat(dep)
			if err != nil {
				return nil, err
			}
			mode := info.Mode()
			if mode&os.ModeSymlink == os.ModeSymlink {
				l, err := os.Readlink(dep)
				if err != nil {
					return nil, err
				}
				i.Files[relPath] = isolated.File{Link: newString(l)}
			} else {
				i.Files[relPath] = isolated.File{Mode: newInt(int(mode.Perm())), Size: newInt64(info.Size())}
				fileItems = append(fileItems, arch.PushFile(relPath, dep, -info.Size()))
			}
		}
	}

	for _, item := range fileItems {
		item.WaitForHashed()
		if err = item.Error(); err != nil {
			return nil, err
		}
		f := i.Files[item.DisplayName]
		f.Digest = item.Digest()
		i.Files[item.DisplayName] = f
	}
	// Avoid duplicated entries in includes.
	// TODO(tandrii): add test to reproduce the problem.
	includesSet := map[isolated.HexDigest]bool{}
	for _, item := range dirItems {
		item.WaitForHashed()
		if err = item.Error(); err != nil {
			return nil, err
		}
		includesSet[item.Digest()] = true
	}
	for digest := range includesSet {
		i.Includes = append(i.Includes, digest)
	}
	// Make the includes list deterministic.
	sort.Sort(i.Includes)

	raw := &bytes.Buffer{}
	if err = json.NewEncoder(raw).Encode(i); err != nil {
		return nil, err
	}

	if err := ioutil.WriteFile(opts.Isolated, raw.Bytes(), 0644); err != nil {
		return nil, err
	}
	return arch.Push(displayName, isolatedclient.NewBytesSource(raw.Bytes()), 0), nil
}
<|endoftext|>


<commit_before>// IronMQ (elastic message queue) client library
package mq

import (
	"errors"
	"time"

	"github.com/iron-io/iron_go/api"
	"github.com/iron-io/iron_go/config"
)

type Queue struct {
	Settings config.Settings
	Name     string
}

type QueueSubscriber struct {
	URL string `json:"url"`
}

type QueueInfo struct {
	Id              string            `json:"id,omitempty"`
	Name            string            `json:"name,omitempty"`
	Size            int               `json:"size,omitempty"`
	Reserved        int               `json:"reserved,omitempty"`
	TotalMessages   int               `json:"total_messages,omitempty"`
	MaxReqPerMinute int               `json:"max_req_per_minute,omitempty"`
	Subscribers     []QueueSubscriber `json:"subscribers,omitempty"`
	PushType        string            `json:"push_type,omitempty"`
}

type Message struct {
	Id   string `json:"id,omitempty"`
	Body string `json:"body"`
	// Timeout is the amount of time in seconds allowed for processing the
	// message.
	Timeout int64 `json:"timeout,omitempty"`
	// Delay is the amount of time in seconds to wait before adding the message
	// to the queue.
	Delay int64 `json:"delay,omitempty"`
	q     Queue
}

type PushStatus struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
}

type Subscriber struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
	URL        string `json:"url"`
}

func New(queueName string) *Queue {
	return &Queue{Settings: config.Config("iron_mq"), Name: queueName}
}

func (q Queue) queues(s ...string) *api.URL { return api.Action(q.Settings, "queues", s...) }

func (q Queue) ListQueues(page, perPage int) (queues []Queue, err error) {
	out := []struct {
		Id         string
		Project_id string
		Name       string
	}{}

	err = q.queues().
		QueryAdd("page", "%d", page).
		QueryAdd("per_page", "%d", perPage).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	queues = make([]Queue, 0, len(out))
	for _, item := range out {
		queues = append(queues, Queue{
			Settings: q.Settings,
			Name:     item.Name,
		})
	}

	return
}

func (q Queue) Info() (QueueInfo, error) {
	qi := QueueInfo{}
	err := q.queues(q.Name).Req("GET", nil, &qi)
	return qi, err
}

func (q Queue) Subscribe(pushType string, subscribers ...string) (err error) {
	in := QueueInfo{
		PushType:    pushType,
		Subscribers: make([]QueueSubscriber, len(subscribers)),
	}
	for i, subscriber := range subscribers {
		in.Subscribers[i].URL = subscriber
	}
	return q.queues(q.Name).Req("POST", &in, nil)
}

func (q Queue) PushString(body string) (id string, err error) {
	ids, err := q.PushStrings(body)
	if err != nil {
		return
	}
	return ids[0], nil
}

// Push adds one or more messages to the end of the queue using IronMQ's defaults:
//	timeout - 60 seconds
//	delay - none
//
// Identical to PushMessages with Message{Timeout: 60, Delay: 0}
func (q Queue) PushStrings(bodies ...string) (ids []string, err error) {
	msgs := make([]*Message, 0, len(bodies))
	for _, body := range bodies {
		msgs = append(msgs, &Message{Body: body})
	}

	return q.PushMessages(msgs...)
}

func (q Queue) PushMessage(msg *Message) (id string, err error) {
	ids, err := q.PushMessages(msg)
	if err != nil {
		return
	}
	return ids[0], nil
}

func (q Queue) PushMessages(msgs ...*Message) (ids []string, err error) {
	in := struct {
		Messages []*Message `json:"messages"`
	}{Messages: msgs}

	out := struct {
		IDs []string `json:"ids"`
		Msg string   `json:"msg"`
	}{}

	err = q.queues(q.Name, "messages").Req("POST", &in, &out)
	return out.IDs, err
}

// Get reserves a message from the queue.
// The message will not be deleted, but will be reserved until the timeout
// expires. If the timeout expires before the message is deleted, the message
// will be placed back onto the queue.
// As a result, be sure to Delete a message after you're done with it.
func (q Queue) Get() (msg *Message, err error) {
	msgs, err := q.GetN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// get N messages
func (q Queue) GetN(n int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages").
		QueryAdd("n", "%d", n).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

// Delete all messages in the queue
func (q Queue) Clear() (err error) {
	return q.queues(q.Name, "clear").Req("POST", nil, nil)
}

// Delete message from queue
func (q Queue) DeleteMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId).Req("DELETE", nil, nil)
}

// Reset timeout of message to keep it reserved
func (q Queue) TouchMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId, "touch").Req("POST", nil, nil)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (q Queue) ReleaseMessage(msgId string, delay int64) (err error) {
	in := struct {
		Delay int64 `json:"delay"`
	}{Delay: delay}
	return q.queues(q.Name, "messages", msgId, "release").Req("POST", &in, nil)
}

func (q Queue) MessageSubscribers(msgId string) ([]*Subscriber, error) {
	out := struct {
		Subscribers []*Subscriber `json:"subscribers"`
	}{}
	err := q.queues(q.Name, "messages", msgId, "subscribers").Req("GET", nil, &out)
	return out.Subscribers, err
}

func (q Queue) MessageSubscribersPollN(msgId string, n int) ([]*Subscriber, error) {
	subs, err := q.MessageSubscribers(msgId)
	for {
		time.Sleep(100 * time.Millisecond)
		subs, err = q.MessageSubscribers(msgId)
		if err != nil {
			return subs, err
		}
		if len(subs) >= n && actualPushStatus(subs) {
			return subs, nil
		}
	}
	return subs, err
}

func actualPushStatus(subs []*Subscriber) bool {
	for _, sub := range subs {
		if sub.Status == "queued" {
			return false
		}
	}

	return true
}

// Delete message from queue
func (m Message) Delete() (err error) {
	return m.q.DeleteMessage(m.Id)
}

// Reset timeout of message to keep it reserved
func (m Message) Touch() (err error) {
	return m.q.TouchMessage(m.Id)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (m Message) Release(delay int64) (err error) {
	return m.q.ReleaseMessage(m.Id, delay)
}

func (m Message) Subscribers() (interface{}, error) {
	return m.q.MessageSubscribers(m.Id)
}
<commit_msg>change Queue.Subscribe to new api<commit_after>// IronMQ (elastic message queue) client library
package mq

import (
	"errors"
	"time"

	"github.com/iron-io/iron_go/api"
	"github.com/iron-io/iron_go/config"
)

type Queue struct {
	Settings config.Settings
	Name     string
}

type QueueSubscriber struct {
	URL string `json:"url"`
}

type QueueInfo struct {
	Id            string            `json:"id,omitempty"`
	Name          string            `json:"name,omitempty"`
	PushType      string            `json:"push_type,omitempty"`
	Reserved      int               `json:"reserved,omitempty"`
	RetriesDelay  int               `json:"retries,omitempty"`
	Retries       int               `json:"retries_delay,omitempty"`
	Size          int               `json:"size,omitempty"`
	Subscribers   []QueueSubscriber `json:"subscribers,omitempty"`
	TotalMessages int               `json:"total_messages,omitempty"`
}

type Message struct {
	Id   string `json:"id,omitempty"`
	Body string `json:"body"`
	// Timeout is the amount of time in seconds allowed for processing the
	// message.
	Timeout int64 `json:"timeout,omitempty"`
	// Delay is the amount of time in seconds to wait before adding the message
	// to the queue.
	Delay int64 `json:"delay,omitempty"`
	q     Queue
}

type PushStatus struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
}

type Subscriber struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
	URL        string `json:"url"`
}

func New(queueName string) *Queue {
	return &Queue{Settings: config.Config("iron_mq"), Name: queueName}
}

func (q Queue) queues(s ...string) *api.URL { return api.Action(q.Settings, "queues", s...) }

func (q Queue) ListQueues(page, perPage int) (queues []Queue, err error) {
	out := []struct {
		Id         string
		Project_id string
		Name       string
	}{}

	err = q.queues().
		QueryAdd("page", "%d", page).
		QueryAdd("per_page", "%d", perPage).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	queues = make([]Queue, 0, len(out))
	for _, item := range out {
		queues = append(queues, Queue{
			Settings: q.Settings,
			Name:     item.Name,
		})
	}

	return
}

func (q Queue) Info() (QueueInfo, error) {
	qi := QueueInfo{}
	err := q.queues(q.Name).Req("GET", nil, &qi)
	return qi, err
}

type Subscription struct {
	PushType     string
	Retries      int
	RetriesDelay int
}

func (q Queue) Subscribe(subscription Subscription, subscribers ...string) (err error) {
	in := QueueInfo{
		PushType:     subscription.PushType,
		Retries:      subscription.Retries,
		RetriesDelay: subscription.RetriesDelay,
		Subscribers:  make([]QueueSubscriber, len(subscribers)),
	}
	for i, subscriber := range subscribers {
		in.Subscribers[i].URL = subscriber
	}
	return q.queues(q.Name).Req("POST", &in, nil)
}

func (q Queue) PushString(body string) (id string, err error) {
	ids, err := q.PushStrings(body)
	if err != nil {
		return
	}
	return ids[0], nil
}

// Push adds one or more messages to the end of the queue using IronMQ's defaults:
//	timeout - 60 seconds
//	delay - none
//
// Identical to PushMessages with Message{Timeout: 60, Delay: 0}
func (q Queue) PushStrings(bodies ...string) (ids []string, err error) {
	msgs := make([]*Message, 0, len(bodies))
	for _, body := range bodies {
		msgs = append(msgs, &Message{Body: body})
	}

	return q.PushMessages(msgs...)
}

func (q Queue) PushMessage(msg *Message) (id string, err error) {
	ids, err := q.PushMessages(msg)
	if err != nil {
		return
	}
	return ids[0], nil
}

func (q Queue) PushMessages(msgs ...*Message) (ids []string, err error) {
	in := struct {
		Messages []*Message `json:"messages"`
	}{Messages: msgs}

	out := struct {
		IDs []string `json:"ids"`
		Msg string   `json:"msg"`
	}{}

	err = q.queues(q.Name, "messages").Req("POST", &in, &out)
	return out.IDs, err
}

// Get reserves a message from the queue.
// The message will not be deleted, but will be reserved until the timeout
// expires. If the timeout expires before the message is deleted, the message
// will be placed back onto the queue.
// As a result, be sure to Delete a message after you're done with it.
func (q Queue) Get() (msg *Message, err error) {
	msgs, err := q.GetN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// get N messages
func (q Queue) GetN(n int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages").
		QueryAdd("n", "%d", n).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

// Delete all messages in the queue
func (q Queue) Clear() (err error) {
	return q.queues(q.Name, "clear").Req("POST", nil, nil)
}

// Delete message from queue
func (q Queue) DeleteMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId).Req("DELETE", nil, nil)
}

// Reset timeout of message to keep it reserved
func (q Queue) TouchMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId, "touch").Req("POST", nil, nil)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (q Queue) ReleaseMessage(msgId string, delay int64) (err error) {
	in := struct {
		Delay int64 `json:"delay"`
	}{Delay: delay}
	return q.queues(q.Name, "messages", msgId, "release").Req("POST", &in, nil)
}

func (q Queue) MessageSubscribers(msgId string) ([]*Subscriber, error) {
	out := struct {
		Subscribers []*Subscriber `json:"subscribers"`
	}{}
	err := q.queues(q.Name, "messages", msgId, "subscribers").Req("GET", nil, &out)
	return out.Subscribers, err
}

func (q Queue) MessageSubscribersPollN(msgId string, n int) ([]*Subscriber, error) {
	subs, err := q.MessageSubscribers(msgId)
	for {
		time.Sleep(100 * time.Millisecond)
		subs, err = q.MessageSubscribers(msgId)
		if err != nil {
			return subs, err
		}
		if len(subs) >= n && actualPushStatus(subs) {
			return subs, nil
		}
	}
	return subs, err
}

func actualPushStatus(subs []*Subscriber) bool {
	for _, sub := range subs {
		if sub.Status == "queued" {
			return false
		}
	}

	return true
}

// Delete message from queue
func (m Message) Delete() (err error) {
	return m.q.DeleteMessage(m.Id)
}

// Reset timeout of message to keep it reserved
func (m Message) Touch() (err error) {
	return m.q.TouchMessage(m.Id)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (m Message) Release(delay int64) (err error) {
	return m.q.ReleaseMessage(m.Id, delay)
}

func (m Message) Subscribers() (interface{}, error) {
	return m.q.MessageSubscribers(m.Id)
}
<|endoftext|>


<commit_before>package xorm

import (
	//"crypto/tls"
	"database/sql"
	"errors"
	"fmt"
	//"regexp"
	"strconv"
	"strings"
	//"time"
)

type mssql struct {
	base
	quoteFilter Filter
}

type mssqlParser struct {
}

func (p *mssqlParser) parse(driverName, dataSourceName string) (*uri, error) {
	return &uri{dbName: "xorm_test", dbType: MSSQL}, nil
}

func (db *mssql) Init(drivername, uri string) error {
	db.quoteFilter = &QuoteFilter{}
	return db.base.init(&mssqlParser{}, drivername, uri)
}

func (db *mssql) SqlType(c *Column) string {
	var res string
	switch t := c.SQLType.Name; t {
	case Bool:
		res = TinyInt
	case Serial:
		c.IsAutoIncrement = true
		c.IsPrimaryKey = true
		c.Nullable = false
		res = Int
	case BigSerial:
		c.IsAutoIncrement = true
		c.IsPrimaryKey = true
		c.Nullable = false
		res = BigInt
	case Bytea, Blob, Binary, TinyBlob, MediumBlob, LongBlob:
		res = VarBinary
		if c.Length == 0 {
			c.Length = 50
		}
	case TimeStamp:
		res = DateTime
	case TimeStampz:
		res = "DATETIMEOFFSET"
		c.Length = 7
	case MediumInt:
		res = Int
	case MediumText, TinyText, LongText:
		res = Text
	case Double:
		res = Real
	default:
		res = t
	}

	if res == Int {
		return Int
	}

	var hasLen1 bool = (c.Length > 0)
	var hasLen2 bool = (c.Length2 > 0)
	if hasLen1 {
		res += "(" + strconv.Itoa(c.Length) + ")"
	} else if hasLen2 {
		res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
	}
	return res
}

func (db *mssql) SupportInsertMany() bool {
	return true
}

func (db *mssql) QuoteStr() string {
	return "\""
}

func (db *mssql) SupportEngine() bool {
	return false
}

func (db *mssql) AutoIncrStr() string {
	return "IDENTITY"
}

func (db *mssql) SupportCharset() bool {
	return false
}

func (db *mssql) IndexOnTable() bool {
	return true
}

func (db *mssql) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
	args := []interface{}{idxName}
	sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?"
	return sql, args
}

func (db *mssql) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
	args := []interface{}{tableName, colName}
	sql := `SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "COLUMN_NAME" = ?`
	return sql, args
}

func (db *mssql) TableCheckSql(tableName string) (string, []interface{}) {
	args := []interface{}{}
	sql := "select * from sysobjects where id = object_id(N'" + tableName + "') and OBJECTPROPERTY(id, N'IsUserTable') = 1"
	return sql, args
}

func (db *mssql) GetColumns(tableName string) ([]string, map[string]*Column, error) {
	args := []interface{}{}
	s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale
from sys.columns a left join sys.types b on a.user_type_id=b.user_type_id
where a.object_id=object_id('` + tableName + `')`
	cnn, err := sql.Open(db.driverName, db.dataSourceName)
	if err != nil {
		return nil, nil, err
	}
	defer cnn.Close()
	res, err := query(cnn, s, args...)
	if err != nil {
		return nil, nil, err
	}
	cols := make(map[string]*Column)
	colSeq := make([]string, 0)
	for _, record := range res {
		col := new(Column)
		col.Indexes = make(map[string]bool)
		for name, content := range record {
			switch name {
			case "name":
				col.Name = strings.Trim(string(content), "` ")
			case "ctype":
				ct := strings.ToUpper(string(content))
				switch ct {
				case "DATETIMEOFFSET":
					col.SQLType = SQLType{TimeStampz, 0, 0}
				default:
					if _, ok := sqlTypes[ct]; ok {
						col.SQLType = SQLType{ct, 0, 0}
					} else {
						return nil, nil, errors.New(fmt.Sprintf("unknow colType %v", ct))
					}
				}

			case "max_length":
				len1, err := strconv.Atoi(strings.TrimSpace(string(content)))
				if err != nil {
					return nil, nil, err
				}
				col.Length = len1
			}
		}
		if col.SQLType.IsText() {
			if col.Default != "" {
				col.Default = "'" + col.Default + "'"
			}
		}
		cols[col.Name] = col
		colSeq = append(colSeq, col.Name)
	}
	return colSeq, cols, nil
}

func (db *mssql) GetTables() ([]*Table, error) {
	args := []interface{}{}
	s := `select name from sysobjects where xtype ='U'`
	cnn, err := sql.Open(db.driverName, db.dataSourceName)
	if err != nil {
		return nil, err
	}
	defer cnn.Close()
	res, err := query(cnn, s, args...)
	if err != nil {
		return nil, err
	}

	tables := make([]*Table, 0)
	for _, record := range res {
		table := new(Table)
		for name, content := range record {
			switch name {
			case "name":
				table.Name = strings.Trim(string(content), "` ")
			}
		}
		tables = append(tables, table)
	}
	return tables, nil
}

func (db *mssql) GetIndexes(tableName string) (map[string]*Index, error) {
	args := []interface{}{tableName}
	s := `SELECT
IXS.NAME                    AS  [INDEX_NAME],
C.NAME                      AS  [COLUMN_NAME],
IXS.is_unique AS [IS_UNIQUE],
CASE    IXCS.IS_INCLUDED_COLUMN
WHEN    0   THEN    'NONE'
ELSE    'INCLUDED'  END     AS  [IS_INCLUDED_COLUMN]
FROM SYS.INDEXES IXS
INNER JOIN SYS.INDEX_COLUMNS   IXCS
ON IXS.OBJECT_ID=IXCS.OBJECT_ID  AND IXS.INDEX_ID = IXCS.INDEX_ID
INNER   JOIN SYS.COLUMNS C  ON IXS.OBJECT_ID=C.OBJECT_ID
AND IXCS.COLUMN_ID=C.COLUMN_ID
WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
`
	cnn, err := sql.Open(db.driverName, db.dataSourceName)
	if err != nil {
		return nil, err
	}
	defer cnn.Close()
	res, err := query(cnn, s, args...)
	if err != nil {
		return nil, err
	}

	indexes := make(map[string]*Index, 0)
	for _, record := range res {
		fmt.Println("-----", record, "-----")
		var indexType int
		var indexName, colName string
		for name, content := range record {
			switch name {
			case "IS_UNIQUE":
				i, err := strconv.ParseBool(string(content))
				if err != nil {
					return nil, err
				}

				fmt.Println(name, string(content), i)

				if i {
					indexType = UniqueType
				} else {
					indexType = IndexType
				}
			case "INDEX_NAME":
				indexName = string(content)
			case "COLUMN_NAME":
				colName = strings.Trim(string(content), "` ")
			}
		}

		if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
			indexName = indexName[5+len(tableName) : len(indexName)]
		}

		var index *Index
		var ok bool
		if index, ok = indexes[indexName]; !ok {
			index = new(Index)
			index.Type = indexType
			index.Name = indexName
			indexes[indexName] = index
		}
		index.AddColumn(colName)
		fmt.Print("------end------")
	}
	return indexes, nil
}
<commit_msg>remove debug info<commit_after>package xorm

import (
	//"crypto/tls"
	"database/sql"
	"errors"
	"fmt"
	//"regexp"
	"strconv"
	"strings"
	//"time"
)

type mssql struct {
	base
	quoteFilter Filter
}

type mssqlParser struct {
}

func (p *mssqlParser) parse(driverName, dataSourceName string) (*uri, error) {
	return &uri{dbName: "xorm_test", dbType: MSSQL}, nil
}

func (db *mssql) Init(drivername, uri string) error {
	db.quoteFilter = &QuoteFilter{}
	return db.base.init(&mssqlParser{}, drivername, uri)
}

func (db *mssql) SqlType(c *Column) string {
	var res string
	switch t := c.SQLType.Name; t {
	case Bool:
		res = TinyInt
	case Serial:
		c.IsAutoIncrement = true
		c.IsPrimaryKey = true
		c.Nullable = false
		res = Int
	case BigSerial:
		c.IsAutoIncrement = true
		c.IsPrimaryKey = true
		c.Nullable = false
		res = BigInt
	case Bytea, Blob, Binary, TinyBlob, MediumBlob, LongBlob:
		res = VarBinary
		if c.Length == 0 {
			c.Length = 50
		}
	case TimeStamp:
		res = DateTime
	case TimeStampz:
		res = "DATETIMEOFFSET"
		c.Length = 7
	case MediumInt:
		res = Int
	case MediumText, TinyText, LongText:
		res = Text
	case Double:
		res = Real
	default:
		res = t
	}

	if res == Int {
		return Int
	}

	var hasLen1 bool = (c.Length > 0)
	var hasLen2 bool = (c.Length2 > 0)
	if hasLen1 {
		res += "(" + strconv.Itoa(c.Length) + ")"
	} else if hasLen2 {
		res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
	}
	return res
}

func (db *mssql) SupportInsertMany() bool {
	return true
}

func (db *mssql) QuoteStr() string {
	return "\""
}

func (db *mssql) SupportEngine() bool {
	return false
}

func (db *mssql) AutoIncrStr() string {
	return "IDENTITY"
}

func (db *mssql) SupportCharset() bool {
	return false
}

func (db *mssql) IndexOnTable() bool {
	return true
}

func (db *mssql) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
	args := []interface{}{idxName}
	sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?"
	return sql, args
}

func (db *mssql) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
	args := []interface{}{tableName, colName}
	sql := `SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "COLUMN_NAME" = ?`
	return sql, args
}

func (db *mssql) TableCheckSql(tableName string) (string, []interface{}) {
	args := []interface{}{}
	sql := "select * from sysobjects where id = object_id(N'" + tableName + "') and OBJECTPROPERTY(id, N'IsUserTable') = 1"
	return sql, args
}

func (db *mssql) GetColumns(tableName string) ([]string, map[string]*Column, error) {
	args := []interface{}{}
	s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale
from sys.columns a left join sys.types b on a.user_type_id=b.user_type_id
where a.object_id=object_id('` + tableName + `')`
	cnn, err := sql.Open(db.driverName, db.dataSourceName)
	if err != nil {
		return nil, nil, err
	}
	defer cnn.Close()
	res, err := query(cnn, s, args...)
	if err != nil {
		return nil, nil, err
	}
	cols := make(map[string]*Column)
	colSeq := make([]string, 0)
	for _, record := range res {
		col := new(Column)
		col.Indexes = make(map[string]bool)
		for name, content := range record {
			switch name {
			case "name":
				col.Name = strings.Trim(string(content), "` ")
			case "ctype":
				ct := strings.ToUpper(string(content))
				switch ct {
				case "DATETIMEOFFSET":
					col.SQLType = SQLType{TimeStampz, 0, 0}
				default:
					if _, ok := sqlTypes[ct]; ok {
						col.SQLType = SQLType{ct, 0, 0}
					} else {
						return nil, nil, errors.New(fmt.Sprintf("unknow colType %v", ct))
					}
				}

			case "max_length":
				len1, err := strconv.Atoi(strings.TrimSpace(string(content)))
				if err != nil {
					return nil, nil, err
				}
				col.Length = len1
			}
		}
		if col.SQLType.IsText() {
			if col.Default != "" {
				col.Default = "'" + col.Default + "'"
			}
		}
		cols[col.Name] = col
		colSeq = append(colSeq, col.Name)
	}
	return colSeq, cols, nil
}

func (db *mssql) GetTables() ([]*Table, error) {
	args := []interface{}{}
	s := `select name from sysobjects where xtype ='U'`
	cnn, err := sql.Open(db.driverName, db.dataSourceName)
	if err != nil {
		return nil, err
	}
	defer cnn.Close()
	res, err := query(cnn, s, args...)
	if err != nil {
		return nil, err
	}

	tables := make([]*Table, 0)
	for _, record := range res {
		table := new(Table)
		for name, content := range record {
			switch name {
			case "name":
				table.Name = strings.Trim(string(content), "` ")
			}
		}
		tables = append(tables, table)
	}
	return tables, nil
}

func (db *mssql) GetIndexes(tableName string) (map[string]*Index, error) {
	args := []interface{}{tableName}
	s := `SELECT
IXS.NAME                    AS  [INDEX_NAME],
C.NAME                      AS  [COLUMN_NAME],
IXS.is_unique AS [IS_UNIQUE],
CASE    IXCS.IS_INCLUDED_COLUMN
WHEN    0   THEN    'NONE'
ELSE    'INCLUDED'  END     AS  [IS_INCLUDED_COLUMN]
FROM SYS.INDEXES IXS
INNER JOIN SYS.INDEX_COLUMNS   IXCS
ON IXS.OBJECT_ID=IXCS.OBJECT_ID  AND IXS.INDEX_ID = IXCS.INDEX_ID
INNER   JOIN SYS.COLUMNS C  ON IXS.OBJECT_ID=C.OBJECT_ID
AND IXCS.COLUMN_ID=C.COLUMN_ID
WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
`
	cnn, err := sql.Open(db.driverName, db.dataSourceName)
	if err != nil {
		return nil, err
	}
	defer cnn.Close()
	res, err := query(cnn, s, args...)
	if err != nil {
		return nil, err
	}

	indexes := make(map[string]*Index, 0)
	for _, record := range res {
		var indexType int
		var indexName, colName string
		for name, content := range record {
			switch name {
			case "IS_UNIQUE":
				i, err := strconv.ParseBool(string(content))
				if err != nil {
					return nil, err
				}

				if i {
					indexType = UniqueType
				} else {
					indexType = IndexType
				}
			case "INDEX_NAME":
				indexName = string(content)
			case "COLUMN_NAME":
				colName = strings.Trim(string(content), "` ")
			}
		}

		if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
			indexName = indexName[5+len(tableName) : len(indexName)]
		}

		var index *Index
		var ok bool
		if index, ok = indexes[indexName]; !ok {
			index = new(Index)
			index.Type = indexType
			index.Name = indexName
			indexes[indexName] = index
		}
		index.AddColumn(colName)
	}
	return indexes, nil
}
<|endoftext|>


<commit_before>// +build functional

package cri_containerd

import (
	"context"
	"net"
	"testing"
	"time"

	_ "github.com/Microsoft/hcsshim/test/functional/manifest"
	"google.golang.org/grpc"
	runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
)

const (
	daemonAddress                = "tcp://127.0.0.1:2376"
	connectTimeout               = time.Second * 10
	testNamespace                = "cri-containerd-test"
	wcowProcessRuntimeHandler    = "default-debug"
	wcowHypervisorRuntimeHandler = "wcow-debug"
	lcowRuntimeHandler           = "lcow-debug"
	imageWindowsRS5Nanoserver    = "mcr.microsoft.com/windows/nanoserver:1809"
	imageWindowsRS5Servercore    = "mcr.microsoft.com/windows/servercore:1809"
	imageLcowK8sPause            = "k8s.gcr.io/pause"
	imageLcowAlpine              = "docker.io/library/alpine"
)

func newTestRuntimeClient(t *testing.T) runtime.RuntimeServiceClient {
	ctx, cancel := context.WithTimeout(context.Background(), connectTimeout)
	defer cancel()
	conn, err := grpc.DialContext(ctx, daemonAddress, grpc.WithInsecure(), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
		return net.DialTimeout("tcp", "127.0.0.1:2376", timeout)
	}))
	if err != nil {
		t.Fatalf("failed to dial runtime client: %v", err)
	}
	return runtime.NewRuntimeServiceClient(conn)
}

func newTestImageClient(t *testing.T) runtime.ImageServiceClient {
	ctx, cancel := context.WithTimeout(context.Background(), connectTimeout)
	defer cancel()
	conn, err := grpc.DialContext(ctx, daemonAddress, grpc.WithInsecure(), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
		return net.DialTimeout("tcp", "127.0.0.1:2376", timeout)
	}))
	if err != nil {
		t.Fatalf("failed to dial runtime client: %v", err)
	}
	return runtime.NewImageServiceClient(conn)
}

func pullRequiredImages(t *testing.T, images []string) {
	pullRequiredImagesWithLabels(t, images, map[string]string{
		"sandbox-platform": "windows/amd64", // Not required for Windows but makes the test safer depending on defaults in the config.
	})
}

func pullRequiredLcowImages(t *testing.T, images []string) {
	pullRequiredImagesWithLabels(t, images, map[string]string{
		"sandbox-platform": "linux/amd64",
	})
}

func pullRequiredImagesWithLabels(t *testing.T, images []string, labels map[string]string) {
	if len(images) < 1 {
		return
	}

	client := newTestImageClient(t)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	sb := &runtime.PodSandboxConfig{
		Labels: labels,
	}
	for _, image := range images {
		_, err := client.PullImage(ctx, &runtime.PullImageRequest{
			Image: &runtime.ImageSpec{
				Image: image,
			},
			SandboxConfig: sb,
		})
		if err != nil {
			t.Fatalf("failed PullImage for image: %s, with error: %v", image, err)
		}
	}
}
<commit_msg>Fix bug in pulling LCOW pause image<commit_after>// +build functional

package cri_containerd

import (
	"context"
	"net"
	"testing"
	"time"

	_ "github.com/Microsoft/hcsshim/test/functional/manifest"
	"google.golang.org/grpc"
	runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
)

const (
	daemonAddress                = "tcp://127.0.0.1:2376"
	connectTimeout               = time.Second * 10
	testNamespace                = "cri-containerd-test"
	wcowProcessRuntimeHandler    = "default-debug"
	wcowHypervisorRuntimeHandler = "wcow-debug"
	lcowRuntimeHandler           = "lcow-debug"
	imageWindowsRS5Nanoserver    = "mcr.microsoft.com/windows/nanoserver:1809"
	imageWindowsRS5Servercore    = "mcr.microsoft.com/windows/servercore:1809"
	imageLcowK8sPause            = "k8s.gcr.io/pause:3.1"
	imageLcowAlpine              = "docker.io/library/alpine:latest"
)

func newTestRuntimeClient(t *testing.T) runtime.RuntimeServiceClient {
	ctx, cancel := context.WithTimeout(context.Background(), connectTimeout)
	defer cancel()
	conn, err := grpc.DialContext(ctx, daemonAddress, grpc.WithInsecure(), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
		return net.DialTimeout("tcp", "127.0.0.1:2376", timeout)
	}))
	if err != nil {
		t.Fatalf("failed to dial runtime client: %v", err)
	}
	return runtime.NewRuntimeServiceClient(conn)
}

func newTestImageClient(t *testing.T) runtime.ImageServiceClient {
	ctx, cancel := context.WithTimeout(context.Background(), connectTimeout)
	defer cancel()
	conn, err := grpc.DialContext(ctx, daemonAddress, grpc.WithInsecure(), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
		return net.DialTimeout("tcp", "127.0.0.1:2376", timeout)
	}))
	if err != nil {
		t.Fatalf("failed to dial runtime client: %v", err)
	}
	return runtime.NewImageServiceClient(conn)
}

func pullRequiredImages(t *testing.T, images []string) {
	pullRequiredImagesWithLabels(t, images, map[string]string{
		"sandbox-platform": "windows/amd64", // Not required for Windows but makes the test safer depending on defaults in the config.
	})
}

func pullRequiredLcowImages(t *testing.T, images []string) {
	pullRequiredImagesWithLabels(t, images, map[string]string{
		"sandbox-platform": "linux/amd64",
	})
}

func pullRequiredImagesWithLabels(t *testing.T, images []string, labels map[string]string) {
	if len(images) < 1 {
		return
	}

	client := newTestImageClient(t)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	sb := &runtime.PodSandboxConfig{
		Labels: labels,
	}
	for _, image := range images {
		_, err := client.PullImage(ctx, &runtime.PullImageRequest{
			Image: &runtime.ImageSpec{
				Image: image,
			},
			SandboxConfig: sb,
		})
		if err != nil {
			t.Fatalf("failed PullImage for image: %s, with error: %v", image, err)
		}
	}
}
<|endoftext|>