<commit_before>package emap

import (
	"errors"
	"reflect"
)

type EMap interface {
	Insert(key interface{}, value interface{}, indices ...interface{}) error
	FetchByKey(key interface{}) (interface{}, error)
	FetchByIndex(index interface{}) ([]interface{}, error)
	DeleteByKey(key interface{}) error
	DeleteByIndex(index interface{}) error
	AddIndex(key interface{}, index interface{}) error
	RemoveIndex(key interface{}, index interface{}) error
	KeyNum() int
	KeyNumOfIndex(index interface{}) int
	IndexNum() int
	IndexNumOfKey(key interface{}) int
	HasKey(key interface{}) bool
	HasIndex(index interface{}) bool
	Transform(callback func(interface{}, interface{}) (interface{}, error)) (map[interface{}]interface{}, error)
	Foreach(callback func(interface{}, interface{}))
}

type ExpirableValue interface {
	IsExpired() bool
}

func NewGenericEMap() EMap {
	instance := new(genericEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	return instance
}

func NewExpirableEMap(interval int) EMap {
	instance := new(genericEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	if interval > 0 {
		instance.interval = interval
		go instance.collect(interval)
	}

	return instance
}

func NewStrictEMap(keySample interface{}, valueSample interface{}, indexSample interface{}) (EMap, error) {
	keyType := reflect.TypeOf(keySample).Kind()
	indexType := reflect.TypeOf(indexSample).Kind()
	valueType := reflect.TypeOf(valueSample).Kind()
	if !isTypeSupported(keyType) || !isTypeSupported(indexType) {
		return nil, errors.New("key or index type not supported")
	}

	instance := new(strictEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	instance.keyType = keyType
	instance.indexType = indexType
	instance.valueType = valueType
	if valueType == reflect.Struct {
		instance.valueStruct = reflect.ValueOf(valueSample).Type().Name()
	}

	return instance, nil
}

func NewUnlockEMap() EMap {
	instance := new(unlockEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	return instance
}

func insert(emap interface{}, key interface{}, value interface{}, indices ...interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; exist {
		return errors.New("key duplicte")
	}

	Keys[key] = indices
	Store[key] = value

	for _, index := range indices {
		if keys, exist := Indices[index]; exist {
			Indices[index] = append(keys, key)
		} else {
			Indices[index] = []interface{}{key}
		}
	}

	return nil
}

func fetchByKey(emap interface{}, key interface{}) (interface{}, error) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})

	if value, exist := Store[key]; exist {
		return value, nil
	}

	return nil, errors.New("key not exist")
}

func fetchByIndex(emap interface{}, index interface{}) ([]interface{}, error) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if keys, exist := Indices[index]; exist {
		i := 0
		values := make([]interface{}, len(keys))
		for _, key := range keys {
			values[i] = Store[key]
			i++
		}
		return values, nil
	}

	return nil, errors.New("index not exist")
}

func deleteByKey(emap interface{}, key interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; !exist {
		return errors.New("key not exist")
	}

	for _, index := range Keys[key] {
		removeIndex(emap, key, index)
	}

	delete(Keys, key)
	delete(Store, key)

	return nil
}

func deleteByIndex(emap interface{}, index interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Indices[index]; !exist {
		return errors.New("index not exist")
	}

	for _, key := range Indices[index] {
		deleteByKey(emap, key)
	}

	return nil
}

func addIndex(emap interface{}, key interface{}, index interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; !exist {
		return errors.New("key not exist")
	}

	for _, each := range Keys[key] {
		if each == index {
			return errors.New("index duplicte")
		}
	}
	Keys[key] = append(Keys[key], index)

	if keys, exist := Indices[index]; exist {
		Indices[index] = append(keys, key)
	} else {
		keys = make([]interface{}, 1)
		keys[0] = key
		Indices[index] = keys
	}

	return nil
}

func removeIndex(emap interface{}, key interface{}, index interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; !exist {
		return errors.New("key not exist")
	}

	if _, exist := Indices[index]; !exist {
		return errors.New("index not exist")
	}

	for i, each := range Keys[key] {
		if each == index {
			if i == len(Keys[key])-1 {
				Keys[key] = Keys[key][:i]
				break
			}
			Keys[key] = append(Keys[key][:i], Keys[key][i+1:]...)
		}
	}

	for i, each := range Indices[index] {
		if each == key {
			if i == len(Indices[index])-1 {
				Indices[index] = Indices[index][:i]
				break
			}
			Indices[index] = append(Indices[index][:i], Indices[index][i+1:]...)
		}
	}
	if len(Indices[index]) == 0 {
		delete(Indices, index)
	}

	return nil
}

func transform(emap interface{}, callback func(interface{}, interface{}) (interface{}, error)) (map[interface{}]interface{}, error) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})

	var err error
	targets := make(map[interface{}]interface{}, len(Store))

	for key, value := range Store {
		targets[key], err = callback(key, value)
		if err != nil {
			return nil, err
		}
	}

	return targets, nil
}

func foreach(emap interface{}, callback func(interface{}, interface{})) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})

	for key, value := range Store {
		callback(key, value)
	}
}
<commit_msg>refactor: make it more pricise<commit_after>package emap

import (
	"errors"
	"reflect"
)

type EMap interface {
	Insert(key interface{}, value interface{}, indices ...interface{}) error
	FetchByKey(key interface{}) (interface{}, error)
	FetchByIndex(index interface{}) ([]interface{}, error)
	DeleteByKey(key interface{}) error
	DeleteByIndex(index interface{}) error
	AddIndex(key interface{}, index interface{}) error
	RemoveIndex(key interface{}, index interface{}) error
	KeyNum() int
	KeyNumOfIndex(index interface{}) int
	IndexNum() int
	IndexNumOfKey(key interface{}) int
	HasKey(key interface{}) bool
	HasIndex(index interface{}) bool
	Transform(callback func(interface{}, interface{}) (interface{}, error)) (map[interface{}]interface{}, error)
	Foreach(callback func(interface{}, interface{}))
}

type ExpirableValue interface {
	IsExpired() bool
}

func NewGenericEMap() EMap {
	instance := new(genericEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	return instance
}

func NewExpirableEMap(interval int) EMap {
	instance := new(genericEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	if interval > 0 {
		instance.interval = interval
		go instance.collect(interval)
	}

	return instance
}

func NewStrictEMap(keySample interface{}, valueSample interface{}, indexSample interface{}) (EMap, error) {
	keyType := reflect.TypeOf(keySample).Kind()
	indexType := reflect.TypeOf(indexSample).Kind()
	valueType := reflect.TypeOf(valueSample).Kind()
	if !isTypeSupported(keyType) || !isTypeSupported(indexType) {
		return nil, errors.New("key or index type not supported")
	}

	instance := new(strictEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	instance.keyType = keyType
	instance.indexType = indexType
	instance.valueType = valueType
	if valueType == reflect.Struct {
		instance.valueStruct = reflect.ValueOf(valueSample).Type().Name()
	}

	return instance, nil
}

func NewUnlockEMap() EMap {
	instance := new(unlockEMap)
	instance.Store = make(map[interface{}]interface{})
	instance.Keys = make(map[interface{}][]interface{})
	instance.Indices = make(map[interface{}][]interface{})

	return instance
}

func insert(emap interface{}, key interface{}, value interface{}, indices ...interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; exist {
		return errors.New("key duplicte")
	}

	Keys[key] = indices
	Store[key] = value

	for _, index := range indices {
		if keys, exist := Indices[index]; exist {
			Indices[index] = append(keys, key)
		} else {
			Indices[index] = []interface{}{key}
		}
	}

	return nil
}

func fetchByKey(emap interface{}, key interface{}) (interface{}, error) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})

	if value, exist := Store[key]; exist {
		return value, nil
	}

	return nil, errors.New("key not exist")
}

func fetchByIndex(emap interface{}, index interface{}) ([]interface{}, error) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if keys, exist := Indices[index]; exist {
		i := 0
		values := make([]interface{}, len(keys))
		for _, key := range keys {
			values[i] = Store[key]
			i++
		}
		return values, nil
	}

	return nil, errors.New("index not exist")
}

func deleteByKey(emap interface{}, key interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; !exist {
		return errors.New("key not exist")
	}

	for _, index := range Keys[key] {
		removeIndex(emap, key, index)
	}

	delete(Keys, key)
	delete(Store, key)

	return nil
}

func deleteByIndex(emap interface{}, index interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Indices[index]; !exist {
		return errors.New("index not exist")
	}

	for _, key := range Indices[index] {
		deleteByKey(emap, key)
	}

	return nil
}

func addIndex(emap interface{}, key interface{}, index interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; !exist {
		return errors.New("key not exist")
	}

	for _, each := range Keys[key] {
		if each == index {
			return errors.New("index duplicte")
		}
	}
	Keys[key] = append(Keys[key], index)

	if keys, exist := Indices[index]; exist {
		Indices[index] = append(keys, key)
	} else {
		Indices[index] = []interface{}{key}
	}

	return nil
}

func removeIndex(emap interface{}, key interface{}, index interface{}) error {
	Object := reflect.ValueOf(emap).Elem()
	Keys := Object.FieldByName("Keys").Interface().(map[interface{}][]interface{})
	Indices := Object.FieldByName("Indices").Interface().(map[interface{}][]interface{})

	if _, exist := Keys[key]; !exist {
		return errors.New("key not exist")
	}

	if _, exist := Indices[index]; !exist {
		return errors.New("index not exist")
	}

	for i, each := range Keys[key] {
		if each == index {
			if i == len(Keys[key])-1 {
				Keys[key] = Keys[key][:i]
			} else {
				Keys[key] = append(Keys[key][:i], Keys[key][i+1:]...)
			}
			break
		}
	}

	for i, each := range Indices[index] {
		if each == key {
			if i == len(Indices[index])-1 {
				Indices[index] = Indices[index][:i]
			} else {
				Indices[index] = append(Indices[index][:i], Indices[index][i+1:]...)
			}
			break
		}
	}
	if len(Indices[index]) == 0 {
		delete(Indices, index)
	}

	return nil
}

func transform(emap interface{}, callback func(interface{}, interface{}) (interface{}, error)) (map[interface{}]interface{}, error) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})

	var err error
	targets := make(map[interface{}]interface{}, len(Store))

	for key, value := range Store {
		targets[key], err = callback(key, value)
		if err != nil {
			return nil, err
		}
	}

	return targets, nil
}

func foreach(emap interface{}, callback func(interface{}, interface{})) {
	Object := reflect.ValueOf(emap).Elem()
	Store := Object.FieldByName("Store").Interface().(map[interface{}]interface{})

	for key, value := range Store {
		callback(key, value)
	}
}
<|endoftext|>


<commit_before><commit_msg>Fix logic to detect and create block/char devices<commit_after><|endoftext|>


<commit_before>package mangadownloader

/*
import (
	"archive/zip"
	"fmt"
	"io"
	"os"
)

func main() {
	zipFile, err := os.Create("test.zip")
	if err != nil {
		panic(err)
	}
	defer zipFile.Close()

	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	file, err := os.Open("README.md")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	zipFileWriter, err := zipWriter.Create("test.md")
	if err != nil {
		panic(err)
	}

	written, err := io.Copy(zipFileWriter, file)
	if err != nil {
		panic(err)
	}
	fmt.Println(written)
}
*/
<commit_msg>ooops<commit_after><|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

func infocmd(opt Options) error {
	user := nvls(opt.Info.User, EnvUser)
	repo := nvls(opt.Info.Repo, EnvRepo)
	tag := opt.Upload.Tag

	if user == "" || repo == "" {
		return fmt.Errorf("user and repo need to be passed as arguments")
	}

	/* list all tags */
	tags, err := Tags(user, repo)
	if err != nil {
		return fmt.Errorf("could not fetch tags, %v", err)
	}

	fmt.Println("git tags:")
	for _, tag := range tags {
		fmt.Println("-", tag.String())
	}

	/* list releases + assets */
	fmt.Println("releases:")
	var releases []Release
	if tag == "" {
		/* get all releases */
		vprintf("%v/%v: getting information for all releases\n", user, repo)
		releases, err = Releases(user, repo)
		if err != nil {
			return err
		}
	} else {
		/* get only one release */
		vprintf("%v/%v/%v: getting information for the release\n", user, repo, tag)
		release, err := ReleaseOfTag(user, repo, tag)
		if err != nil {
			return err
		}
		releases = []Release{*release}
	}

	for _, release := range releases {
		fmt.Println("-", release.String())
	}

	return nil
}

func uploadcmd(opt Options) error {
	user := nvls(opt.Upload.User, EnvUser)
	repo := nvls(opt.Upload.Repo, EnvRepo)
	token := nvls(opt.Upload.Token, EnvToken)
	tag := opt.Upload.Tag
	name := opt.Upload.Name
	file := opt.Upload.File

	vprintln("uploading...")

	if file == nil {
		return fmt.Errorf("provided file was not valid")
	}

	if err := ValidateCredentials(user, repo, token, tag); err != nil {
		return err
	}

	/* find the release corresponding to the entered tag, if any */
	rel, err := ReleaseOfTag(user, repo, tag)
	if err != nil {
		return err
	}

	v := url.Values{}
	v.Set("name", name)

	url := rel.CleanUploadUrl() + "?" + v.Encode()

	resp, err := DoAuthRequest("POST", url, "application/octet-stream",
		token, file)
	if err != nil {
		return fmt.Errorf("can't create upload request to %v, %v", url, err)
	}
	defer resp.Body.Close()

	vprintln("RESPONSE:", resp)
	if resp.StatusCode != http.StatusCreated {
		if msg, err := ToMessage(resp.Body); err == nil {
			return fmt.Errorf("could not upload, status code (%v), %v",
				resp.Status, msg)
		} else {
			return fmt.Errorf("could not upload, status code (%v)", resp.Status)
		}
	}

	if VERBOSITY != 0 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("error while reading response, %v", err)
		}
		vprintln("BODY:", string(body))
	}

	return nil
}

func ValidateCredentials(user, repo, token, tag string) error {
	if user == "" {
		return fmt.Errorf("empty user")
	}
	if repo == "" {
		return fmt.Errorf("empty repo")
	}
	if tag == "" {
		return fmt.Errorf("empty tag")
	}
	if token == "" {
		return fmt.Errorf("empty token")
	}
	return nil
}

func releasecmd(opt Options) error {
	user := nvls(opt.Release.User, EnvUser)
	repo := nvls(opt.Release.Repo, EnvRepo)
	token := nvls(opt.Release.Token, EnvToken)
	tag := opt.Release.Tag
	name := nvls(opt.Release.Name, tag)
	desc := nvls(opt.Release.Desc, tag)
	draft := opt.Release.Draft
	prerelease := opt.Release.Prerelease

	vprintln("releasing...")

	if err := ValidateCredentials(user, repo, token, tag); err != nil {
		return err
	}

	params := ReleaseCreate{
		TagName:    tag,
		Name:       name,
		Body:       desc,
		Draft:      draft,
		Prerelease: prerelease,
	}

	/* when verbosity is off, we don't need the body and we can create a
	 * version with lower overhead (I actually notice this to be slower,
	 * should benchmark...) */
	var (
		reader  io.Reader
		rawjson string
	)
	if VERBOSITY == 0 {
		var writer io.WriteCloser
		reader, writer = io.Pipe()
		enc := json.NewEncoder(writer)
		go func() {
			err := enc.Encode(params)
			defer writer.Close()
			if err != nil {
				/* TODO: we can probably end cleaner here... */
				panic(fmt.Errorf("can't encode release creation params, %v", err))
			}
		}()
	} else {
		jsonBytes, err := json.Marshal(params)
		if err != nil {
			return fmt.Errorf("can't encode release creation params, %v", err)
		}
		rawjson = string(jsonBytes)
		reader = bytes.NewReader(jsonBytes)
	}

	uri := fmt.Sprintf("/repos/%s/%s/releases", user, repo)
	resp, err := DoAuthRequest("POST", ApiURL()+uri, "application/json", token, reader)
	if err != nil {
		return fmt.Errorf("while submitting %v, %v", rawjson, err)
	}
	defer resp.Body.Close()

	vprintln("RESPONSE:", resp)
	if resp.StatusCode != http.StatusCreated {
		if resp.StatusCode == 422 {
			return fmt.Errorf("github returned %v (this is probably because the release already exists)",
				resp.Status)
		}
		return fmt.Errorf("github returned %v", resp.Status)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error while reading response, %v", err)
	}
	vprintln("BODY:", string(body))

	return nil
}

func editcmd(opt Options) error {
	cmdopt := opt.Edit
	user := nvls(cmdopt.User, EnvUser)
	repo := nvls(cmdopt.Repo, EnvRepo)
	token := nvls(cmdopt.Token, EnvToken)
	tag := cmdopt.Tag
	name := nvls(cmdopt.Name, tag)
	desc := nvls(cmdopt.Desc, tag)
	draft := cmdopt.Draft
	prerelease := cmdopt.Prerelease

	vprintln("editing...")

	if err := ValidateCredentials(user, repo, token, tag); err != nil {
		return err
	}

	id, err := IdOfTag(user, repo, tag)
	if err != nil {
		return err
	}

	vprintf("release %v has id %v\n", tag, id)

	/* the release create struct works for editing releases as well */
	params := ReleaseCreate{
		TagName:    tag,
		Name:       name,
		Body:       desc,
		Draft:      draft,
		Prerelease: prerelease,
	}

	/* encode the parameters as JSON, as required by the github API */
	payload, err := json.Marshal(params)
	if err != nil {
		return fmt.Errorf("can't encode release creation params, %v", err)
	}

	uri := fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id)
	resp, err := DoAuthRequest("PATCH", ApiURL()+uri, "application/json",
		token, bytes.NewReader(payload))
	if err != nil {
		return fmt.Errorf("while submitting %v, %v", string(payload), err)
	}
	defer resp.Body.Close()

	vprintln("RESPONSE:", resp)
	if resp.StatusCode != http.StatusOK {
		if resp.StatusCode == 422 {
			return fmt.Errorf("github returned %v (this is probably because the release already exists)",
				resp.Status)
		}
		return fmt.Errorf("github returned unexpected status code %v", resp.Status)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error while reading response, %v", err)
	}
	vprintln("BODY:", string(body))

	return nil
}

func deletecmd(opt Options) error {
	user, repo, token, tag := nvls(opt.Delete.User, EnvUser),
		nvls(opt.Delete.Repo, EnvRepo),
		nvls(opt.Delete.Token, EnvToken),
		opt.Delete.Tag
	vprintln("deleting...")

	id, err := IdOfTag(user, repo, tag)
	if err != nil {
		return err
	}

	vprintf("release %v has id %v\n", tag, id)

	resp, err := httpDelete(ApiURL()+fmt.Sprintf("/repos/%s/%s/releases/%d",
		user, repo, id), token)
	if err != nil {
		return fmt.Errorf("release deletion unsuccesful, %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusNoContent {
		return fmt.Errorf("could not delete the release corresponding to tag %s on repo %s/%s",
			tag, user, repo)
	}

	return nil
}

func httpDelete(url, token string) (*http.Response, error) {
	resp, err := DoAuthRequest("DELETE", url, "application/json", token, nil)
	if err != nil {
		return nil, err
	}

	return resp, nil
}
<commit_msg>refactor and simplify releasecmd<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

func infocmd(opt Options) error {
	user := nvls(opt.Info.User, EnvUser)
	repo := nvls(opt.Info.Repo, EnvRepo)
	tag := opt.Upload.Tag

	if user == "" || repo == "" {
		return fmt.Errorf("user and repo need to be passed as arguments")
	}

	/* list all tags */
	tags, err := Tags(user, repo)
	if err != nil {
		return fmt.Errorf("could not fetch tags, %v", err)
	}

	fmt.Println("git tags:")
	for _, tag := range tags {
		fmt.Println("-", tag.String())
	}

	/* list releases + assets */
	fmt.Println("releases:")
	var releases []Release
	if tag == "" {
		/* get all releases */
		vprintf("%v/%v: getting information for all releases\n", user, repo)
		releases, err = Releases(user, repo)
		if err != nil {
			return err
		}
	} else {
		/* get only one release */
		vprintf("%v/%v/%v: getting information for the release\n", user, repo, tag)
		release, err := ReleaseOfTag(user, repo, tag)
		if err != nil {
			return err
		}
		releases = []Release{*release}
	}

	for _, release := range releases {
		fmt.Println("-", release.String())
	}

	return nil
}

func uploadcmd(opt Options) error {
	user := nvls(opt.Upload.User, EnvUser)
	repo := nvls(opt.Upload.Repo, EnvRepo)
	token := nvls(opt.Upload.Token, EnvToken)
	tag := opt.Upload.Tag
	name := opt.Upload.Name
	file := opt.Upload.File

	vprintln("uploading...")

	if file == nil {
		return fmt.Errorf("provided file was not valid")
	}

	if err := ValidateCredentials(user, repo, token, tag); err != nil {
		return err
	}

	/* find the release corresponding to the entered tag, if any */
	rel, err := ReleaseOfTag(user, repo, tag)
	if err != nil {
		return err
	}

	v := url.Values{}
	v.Set("name", name)

	url := rel.CleanUploadUrl() + "?" + v.Encode()

	resp, err := DoAuthRequest("POST", url, "application/octet-stream",
		token, file)
	if err != nil {
		return fmt.Errorf("can't create upload request to %v, %v", url, err)
	}
	defer resp.Body.Close()

	vprintln("RESPONSE:", resp)
	if resp.StatusCode != http.StatusCreated {
		if msg, err := ToMessage(resp.Body); err == nil {
			return fmt.Errorf("could not upload, status code (%v), %v",
				resp.Status, msg)
		} else {
			return fmt.Errorf("could not upload, status code (%v)", resp.Status)
		}
	}

	if VERBOSITY != 0 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("error while reading response, %v", err)
		}
		vprintln("BODY:", string(body))
	}

	return nil
}

func ValidateCredentials(user, repo, token, tag string) error {
	if user == "" {
		return fmt.Errorf("empty user")
	}
	if repo == "" {
		return fmt.Errorf("empty repo")
	}
	if tag == "" {
		return fmt.Errorf("empty tag")
	}
	if token == "" {
		return fmt.Errorf("empty token")
	}
	return nil
}

func releasecmd(opt Options) error {
	cmdopt := opt.Release
	user := nvls(cmdopt.User, EnvUser)
	repo := nvls(cmdopt.Repo, EnvRepo)
	token := nvls(cmdopt.Token, EnvToken)
	tag := cmdopt.Tag
	name := nvls(cmdopt.Name, tag)
	desc := nvls(cmdopt.Desc, tag)
	draft := cmdopt.Draft
	prerelease := cmdopt.Prerelease

	vprintln("releasing...")

	if err := ValidateCredentials(user, repo, token, tag); err != nil {
		return err
	}

	params := ReleaseCreate{
		TagName:    tag,
		Name:       name,
		Body:       desc,
		Draft:      draft,
		Prerelease: prerelease,
	}

	/* encode params as json */
	payload, err := json.Marshal(params)
	if err != nil {
		return fmt.Errorf("can't encode release creation params, %v", err)
	}
	reader := bytes.NewReader(payload)

	uri := fmt.Sprintf("/repos/%s/%s/releases", user, repo)
	resp, err := DoAuthRequest("POST", ApiURL()+uri, "application/json",
		token, reader)
	if err != nil {
		return fmt.Errorf("while submitting %v, %v", string(payload), err)
	}
	defer resp.Body.Close()

	vprintln("RESPONSE:", resp)
	if resp.StatusCode != http.StatusCreated {
		if resp.StatusCode == 422 {
			return fmt.Errorf("github returned %v (this is probably because the release already exists)",
				resp.Status)
		}
		return fmt.Errorf("github returned %v", resp.Status)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error while reading response, %v", err)
	}
	vprintln("BODY:", string(body))

	return nil
}

func editcmd(opt Options) error {
	cmdopt := opt.Edit
	user := nvls(cmdopt.User, EnvUser)
	repo := nvls(cmdopt.Repo, EnvRepo)
	token := nvls(cmdopt.Token, EnvToken)
	tag := cmdopt.Tag
	name := nvls(cmdopt.Name, tag)
	desc := nvls(cmdopt.Desc, tag)
	draft := cmdopt.Draft
	prerelease := cmdopt.Prerelease

	vprintln("editing...")

	if err := ValidateCredentials(user, repo, token, tag); err != nil {
		return err
	}

	id, err := IdOfTag(user, repo, tag)
	if err != nil {
		return err
	}

	vprintf("release %v has id %v\n", tag, id)

	/* the release create struct works for editing releases as well */
	params := ReleaseCreate{
		TagName:    tag,
		Name:       name,
		Body:       desc,
		Draft:      draft,
		Prerelease: prerelease,
	}

	/* encode the parameters as JSON, as required by the github API */
	payload, err := json.Marshal(params)
	if err != nil {
		return fmt.Errorf("can't encode release creation params, %v", err)
	}

	uri := fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id)
	resp, err := DoAuthRequest("PATCH", ApiURL()+uri, "application/json",
		token, bytes.NewReader(payload))
	if err != nil {
		return fmt.Errorf("while submitting %v, %v", string(payload), err)
	}
	defer resp.Body.Close()

	vprintln("RESPONSE:", resp)
	if resp.StatusCode != http.StatusOK {
		if resp.StatusCode == 422 {
			return fmt.Errorf("github returned %v (this is probably because the release already exists)",
				resp.Status)
		}
		return fmt.Errorf("github returned unexpected status code %v", resp.Status)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error while reading response, %v", err)
	}
	vprintln("BODY:", string(body))

	return nil
}

func deletecmd(opt Options) error {
	user, repo, token, tag := nvls(opt.Delete.User, EnvUser),
		nvls(opt.Delete.Repo, EnvRepo),
		nvls(opt.Delete.Token, EnvToken),
		opt.Delete.Tag
	vprintln("deleting...")

	id, err := IdOfTag(user, repo, tag)
	if err != nil {
		return err
	}

	vprintf("release %v has id %v\n", tag, id)

	resp, err := httpDelete(ApiURL()+fmt.Sprintf("/repos/%s/%s/releases/%d",
		user, repo, id), token)
	if err != nil {
		return fmt.Errorf("release deletion unsuccesful, %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusNoContent {
		return fmt.Errorf("could not delete the release corresponding to tag %s on repo %s/%s",
			tag, user, repo)
	}

	return nil
}

func httpDelete(url, token string) (*http.Response, error) {
	resp, err := DoAuthRequest("DELETE", url, "application/json", token, nil)
	if err != nil {
		return nil, err
	}

	return resp, nil
}
<|endoftext|>


<commit_before>package immortal

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// Control interface
type Control interface {
	GetStatus(socket string) (*Status, error)
	SendSignal(socket, signal string) (*SignalResponse, error)
	FindServices(dir string) ([]*ServiceStatus, error)
	PurgeServices(dir string) error
	Run(command string) ([]byte, error)
}

// ServiceStatus struct
type ServiceStatus struct {
	Name           string
	Socket         string
	Status         *Status
	SignalResponse *SignalResponse
}

// Controller implements Control
type Controller struct{}

// GetStatus returns service status in json format
func (c *Controller) GetStatus(socket string) (*Status, error) {
	status := &Status{}
	if err := GetJSON(socket, "/", status); err != nil {
		return nil, err
	}
	return status, nil
}

// SendSignal send signal to process
func (c *Controller) SendSignal(socket, signal string) (*SignalResponse, error) {
	res := &SignalResponse{}
	if err := GetJSON(socket, fmt.Sprintf("/signal/%s", signal), res); err != nil {
		return nil, err
	}
	return res, nil
}

// FindServices return [name, socket path] of service
func (c *Controller) FindServices(dir string) ([]*ServiceStatus, error) {
	sdir, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	var sockets []*ServiceStatus
	for _, file := range sdir {
		if file.IsDir() {
			socket := filepath.Join(dir, file.Name(), "immortal.sock")
			if fi, err := os.Lstat(socket); err == nil {
				if fi.Mode()&os.ModeType == os.ModeSocket {
					sockets = append(sockets,
						&ServiceStatus{
							file.Name(),
							socket,
							&Status{},
							&SignalResponse{},
						},
					)
				}
			}
		}
	}
	return sockets, nil
}

// PurgeServices remove unused service directory
func (c *Controller) PurgeServices(dir string) error {
	return os.RemoveAll(filepath.Dir(dir))
}

// Run executes a command and print combinedOutput
func (c *Controller) Run(command string) ([]byte, error) {
	parts := strings.Fields(command)
	cmd := parts[0]
	arg := parts[1:len(parts)]
	run := exec.Command(cmd, arg...)
	run.Env = os.Environ()
	stdoutStderr, err := run.CombinedOutput()
	if err != nil {
		return nil, err
	}
	return stdoutStderr, err
}
<commit_msg>timeDuration, stop to test scandir<commit_after>package immortal

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

// Control interface
type Control interface {
	GetStatus(socket string) (*Status, error)
	SendSignal(socket, signal string) (*SignalResponse, error)
	FindServices(dir string) ([]*ServiceStatus, error)
	PurgeServices(dir string) error
	Run(command string) ([]byte, error)
}

// ServiceStatus struct
type ServiceStatus struct {
	Name           string
	Socket         string
	Status         *Status
	SignalResponse *SignalResponse
}

// Controller implements Control
type Controller struct {
	tickDuration time.Duration
	stop         bool
}

// GetStatus returns service status in json format
func (c *Controller) GetStatus(socket string) (*Status, error) {
	status := &Status{}
	if err := GetJSON(socket, "/", status); err != nil {
		return nil, err
	}
	return status, nil
}

// SendSignal send signal to process
func (c *Controller) SendSignal(socket, signal string) (*SignalResponse, error) {
	res := &SignalResponse{}
	if err := GetJSON(socket, fmt.Sprintf("/signal/%s", signal), res); err != nil {
		return nil, err
	}
	return res, nil
}

// FindServices return [name, socket path] of service
func (c *Controller) FindServices(dir string) ([]*ServiceStatus, error) {
	sdir, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	var sockets []*ServiceStatus
	for _, file := range sdir {
		if file.IsDir() {
			socket := filepath.Join(dir, file.Name(), "immortal.sock")
			if fi, err := os.Lstat(socket); err == nil {
				if fi.Mode()&os.ModeType == os.ModeSocket {
					sockets = append(sockets,
						&ServiceStatus{
							file.Name(),
							socket,
							&Status{},
							&SignalResponse{},
						},
					)
				}
			}
		}
	}
	return sockets, nil
}

// PurgeServices remove unused service directory
func (c *Controller) PurgeServices(dir string) error {
	return os.RemoveAll(filepath.Dir(dir))
}

// Run executes a command and print combinedOutput
func (c *Controller) Run(command string) ([]byte, error) {
	parts := strings.Fields(command)
	cmd := parts[0]
	arg := parts[1:len(parts)]
	run := exec.Command(cmd, arg...)
	run.Env = os.Environ()
	stdoutStderr, err := run.CombinedOutput()
	if err != nil {
		return nil, err
	}
	return stdoutStderr, err
}
<|endoftext|>


<commit_before>// Hanayo is the Ripple front-end web server.
package main

// version is the current version of hanayo
const version = "v1.10.1"
<commit_msg>Bump version<commit_after>// Hanayo is the Ripple front-end web server.
package main

// version is the current version of hanayo
const version = "v1.10.2"
<|endoftext|>


<commit_before>/*
Package watcher provides a way to be notified of changes to files
starting from the root of a given directory. Folder paths
to ignore can be customized to fit needs.

Watcher does NOT handle filtering messages. It delegates
this to the user for maximum flexibility.
*/
package watcher
<commit_msg>update doc<commit_after>/*
Package watcher provides a way to be notified of changes to files
starting from the root of a given directory.

The Watcher ignores file/folders that begin with "." or "_".
*/
package watcher
<|endoftext|>


<commit_before>/*
Simplify your golang json usage with a simple hierarchical query.

Installing

	go get github.com/jmoiron/jsonq

Examples

Given some json data like:

	{
		"foo": 1,
		"bar": 2,
		"test": "Hello, world!",
		"baz": 123.1,
		"array": [
			{"foo": 1},
			{"bar": 2},
			{"baz": 3}
		],
		"subobj": {
			"foo": 1,
			"subarray": [1,2,3],
			"subsubobj": {
				"bar": 2,
				"baz": 3,
				"array": ["hello", "world"]
			}
		},
		"bool": true
	}

Decode it into a map[string]interrface{}:

	import (
		"strings"
		"encoding/json"
		"github.com/jmoiron/jsonq"
	)

	data := map[string]interface{}{}
	dec := json.NewDecoder(strings.NewReader(jsonstring))
	dec.Decode(&data)
	jq := jsonq.NewQuery(data)

From here, you can query along different keys and indexes:

	// data["foo"] -> 1
	jq.Int("foo")

	// data["subobj"]["subarray"][1] -> 2
	jq.Int("subobj", "subarray", "1")

	// data["subobj"]["subarray"]["array"][0] -> "hello"
	jq.String("subobj", "subsubobj", "array", "0")

	// data["subobj"] -> map[string]interface{}{"subobj": ...}
	obj, err := jq.Object("subobj")

Notes

Missing keys, out of bounds indexes, and type failures will return errors.
For simplicity, integer keys (ie, {"0": "zero"}) are inaccessible by `jsonq`
as integer strings are assumed to be array indexes.

*/

package documentation
<commit_msg>get rid of newline on top of package jsonq<commit_after>/*
Simplify your golang json usage with a simple hierarchical query.

Installing

	go get github.com/jmoiron/jsonq

Examples

Given some json data like:

	{
		"foo": 1,
		"bar": 2,
		"test": "Hello, world!",
		"baz": 123.1,
		"array": [
			{"foo": 1},
			{"bar": 2},
			{"baz": 3}
		],
		"subobj": {
			"foo": 1,
			"subarray": [1,2,3],
			"subsubobj": {
				"bar": 2,
				"baz": 3,
				"array": ["hello", "world"]
			}
		},
		"bool": true
	}

Decode it into a map[string]interrface{}:

	import (
		"strings"
		"encoding/json"
		"github.com/jmoiron/jsonq"
	)

	data := map[string]interface{}{}
	dec := json.NewDecoder(strings.NewReader(jsonstring))
	dec.Decode(&data)
	jq := jsonq.NewQuery(data)

From here, you can query along different keys and indexes:

	// data["foo"] -> 1
	jq.Int("foo")

	// data["subobj"]["subarray"][1] -> 2
	jq.Int("subobj", "subarray", "1")

	// data["subobj"]["subarray"]["array"][0] -> "hello"
	jq.String("subobj", "subsubobj", "array", "0")

	// data["subobj"] -> map[string]interface{}{"subobj": ...}
	obj, err := jq.Object("subobj")

Notes

Missing keys, out of bounds indexes, and type failures will return errors.
For simplicity, integer keys (ie, {"0": "zero"}) are inaccessible by `jsonq`
as integer strings are assumed to be array indexes.

*/
package jsonq
<|endoftext|>


<commit_before>package redis

import (
	"log"
	"time"

	redis "github.com/go-redis/redis"
	try "github.com/matryer/try"
)

// ConnectToClient Connects to a Redis server
func ConnectToClient(ip string, port string, config Config) *redis.Client {
	client := redis.NewClient(&redis.Options{
		Addr: ip + ":" + port,
	})

	return client
}

// IsWorkingInstance Checks that a registered IP is up and running. Blocking
func IsWorkingInstance(client *redis.Client) (bool, error) {
	err := try.Do(func(attempt int) (bool, error) {
		pong, err := client.Ping().Result()
		if err != nil && pong != "PONG" {
			log.Printf("Client (%s) not ready, will retry", client.Options().Addr)
		} else {
			log.Printf("Client (%s) ready", client.Options().Addr)
		}

		if err != nil {
			time.Sleep(2 * time.Second)
		}

		return true, err // infinite retry
	})

	if err != nil {
		return true, err
	}

	return false, err
}
<commit_msg>Fix logic around what constitutes a connection failure<commit_after>package redis

import (
	"log"
	"time"

	redis "github.com/go-redis/redis"
	try "github.com/matryer/try"
)

// ConnectToClient Connects to a Redis server
func ConnectToClient(ip string, port string, config Config) *redis.Client {
	client := redis.NewClient(&redis.Options{
		Addr: ip + ":" + port,
	})

	return client
}

// IsWorkingInstance Checks that a registered IP is up and running. Blocking
func IsWorkingInstance(client *redis.Client) (bool, error) {
	err := try.Do(func(attempt int) (bool, error) {
		pong, err := client.Ping().Result()
		if err != nil && pong != "PONG" {
			log.Printf("Client (%s) not ready, will retry", client.Options().Addr)
		} else {
			log.Printf("Client (%s) ready", client.Options().Addr)
		}

		if err != nil {
			time.Sleep(2 * time.Second)
		}

		return attempt < 10, err
	})

	if err == nil {
		return true, err
	}

	return false, err
}
<|endoftext|>


<commit_before>// Library rx provides a (jig) generic implementation of Reactive eXtensions.
// It's a generics library for composing asynchronous and event-based programs
// using observable sequences. The library consists of more than a 100 templates
// to enable type-safe programming with observable streams. To use it, you will
// need the jig tool https://github.com/reactivego/jig.
//
// Using the library is very simple. Import the library with the blank
// identifier `_` as the package name:
//	import _ "github.com/reactivego/rx"
// The side effect of this import is that
// generics from the library can now be accessed by the jig tool. Then start
// using generics from the library and run jig to generate code. Take a look at
// the Quick Start guide to see how it all fits together
// https://github.com/reactivego/rx/doc/quickstart.md.
//
// For an overview of all implemented operators, see
// https://github.com/reactivego/rx
package rx

// foo is the first metasyntactic type. Use the jig:type pragma to tell jig that
// Foo is the reference type name for actual type foo. Needed because we're
// generating code into rx.go for foo.

//jig:type Foo foo

type foo int

// bar is the second metasyntactic type. Use the jig:type pragma to tell jig that
// Bar is the reference type name for actual type bar. Needed because we're
// generating code into rx.go for bar.

//jig:type Bar bar

type bar int
<commit_msg>Change the library title in doc.go<commit_after>// Library rx provides a Just-in-time Generics (jig) implementation of Reactive eXtensions (Rx).
// It's a generics library for composing asynchronous and event-based programs
// using observable sequences. The library consists of more than a 100 templates
// to enable type-safe programming with observable streams. To use it, you will
// need the jig tool https://github.com/reactivego/jig.
//
// Using the library is very simple. Import the library with the blank
// identifier `_` as the package name:
//	import _ "github.com/reactivego/rx"
// The side effect of this import is that
// generics from the library can now be accessed by the jig tool. Then start
// using generics from the library and run jig to generate code. Take a look at
// the Quick Start guide to see how it all fits together
// https://github.com/reactivego/rx/doc/quickstart.md.
//
// For an overview of all implemented operators, see
// https://github.com/reactivego/rx
package rx

// foo is the first metasyntactic type. Use the jig:type pragma to tell jig that
// Foo is the reference type name for actual type foo. Needed because we're
// generating code into rx.go for foo.

//jig:type Foo foo

type foo int

// bar is the second metasyntactic type. Use the jig:type pragma to tell jig that
// Bar is the reference type name for actual type bar. Needed because we're
// generating code into rx.go for bar.

//jig:type Bar bar

type bar int
<|endoftext|>


<commit_before>package reflect

import (
	"go/ast"
	"go/token"
)

// Type represents a type of argument.
type Type struct {
	Name    string // Name of the type, e.g. "URL". It is empty if Decl is not nil.
	Package string // Package name, e.g. "template" in case of "html/template".
	Star    bool   // Star indicates whether it is a pointer.
}

// String prints a type name, e.g. "*template.URL", "template.Template",
// "Controller", "int64", etc.
func (t *Type) String() (name string) {
	name = t.Name
	if t.Package != "" {
		name = t.Package + "." + name
	}
	if t.Star {
		name = "*" + name
	}
	return name
}

// processType parses go ast tree related to types into
// Type, a format that is used by this reflect package.
func processType(typ interface{}) *Type {
	fset := token.NewFileSet()
	ast.Print(fset, typ)
	switch v := typ.(type) {
	case *ast.StarExpr:
		// X field contains info about an actual type.
		// Try to receive it.
		t := processType(v.X)
		t.Star = true
		return t
	case *ast.Ident:
		// Initialize a name of the type and return it.
		return &Type{
			Name: v.Name,
		}
	case *ast.SelectorExpr:
		// X contains info about a selector's package.
		// Try to extract it.
		t := processType(v.X)
		return &Type{
			Name:    v.Sel.Name,
			Package: t.Name,
		}
	case *ast.ArrayType:
		// Elt contains info about an actual type, get it.
		t := processType(v.Elt)
		t.Name = "[]" + t.Name // Add "[]" to the type name.
		return t
	case *ast.Ellipsis:
		// Elt contains info about an actual type, extract it.
		t := processType(v.Elt)
		t.Name = "..." + t.Name // Add "..." to the type name.
		return t
	}
	return nil
}
<commit_msg>Removed debugging information<commit_after>package reflect

import (
	"go/ast"
)

// Type represents a type of argument.
type Type struct {
	Name    string // Name of the type, e.g. "URL". It is empty if Decl is not nil.
	Package string // Package name, e.g. "template" in case of "html/template".
	Star    bool   // Star indicates whether it is a pointer.
}

// String prints a type name, e.g. "*template.URL", "template.Template",
// "Controller", "int64", etc.
func (t *Type) String() (name string) {
	name = t.Name
	if t.Package != "" {
		name = t.Package + "." + name
	}
	if t.Star {
		name = "*" + name
	}
	return name
}

// processType parses go ast tree related to types into
// Type, a format that is used by this reflect package.
func processType(typ interface{}) *Type {
	switch v := typ.(type) {
	case *ast.StarExpr:
		// X field contains info about an actual type.
		// Try to receive it.
		t := processType(v.X)
		t.Star = true
		return t
	case *ast.Ident:
		// Initialize a name of the type and return it.
		return &Type{
			Name: v.Name,
		}
	case *ast.SelectorExpr:
		// X contains info about a selector's package.
		// Try to extract it.
		t := processType(v.X)
		return &Type{
			Name:    v.Sel.Name,
			Package: t.Name,
		}
	case *ast.ArrayType:
		// Elt contains info about an actual type, get it.
		t := processType(v.Elt)
		t.Name = "[]" + t.Name // Add "[]" to the type name.
		return t
	case *ast.Ellipsis:
		// Elt contains info about an actual type, extract it.
		t := processType(v.Elt)
		t.Name = "..." + t.Name // Add "..." to the type name.
		return t
	}
	return nil
}
<|endoftext|>


<commit_before>package restful

import (
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"testing"
)

func TestQueryParameter(t *testing.T) {
	hreq := http.Request{Method: "GET"}
	hreq.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
	rreq := Request{Request: &hreq}
	if rreq.QueryParameter("q") != "foo" {
		t.Errorf("q!=foo %#v", rreq)
	}
}

type Anything map[string]interface{}

type Sample struct {
	Value string
}

func TestReadEntityXml(t *testing.T) {
	SetCacheReadEntity(true)
	bodyReader := strings.NewReader("<Sample><Value>42</Value></Sample>")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/xml")
	request := &Request{Request: httpRequest}
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
	if request.bodyContent == nil {
		t.Fatal("no expected cached bytes found")
	}
}

func TestReadEntityXmlNonCached(t *testing.T) {
	SetCacheReadEntity(false)
	bodyReader := strings.NewReader("<Sample><Value>42</Value></Sample>")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/xml")
	request := &Request{Request: httpRequest}
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
	if request.bodyContent != nil {
		t.Fatal("unexpected cached bytes found")
	}
}

func TestReadEntityJson(t *testing.T) {
	bodyReader := strings.NewReader(`{"Value" : "42"}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json")
	request := &Request{Request: httpRequest}
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
}

func TestReadEntityJsonCharset(t *testing.T) {
	bodyReader := strings.NewReader(`{"Value" : "42"}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json; charset=UTF-8")
	request := NewRequest(httpRequest)
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
}

func TestReadEntityJsonLong(t *testing.T) {
	bodyReader := strings.NewReader(`{"Value" : 4899710515899924123}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json")
	request := &Request{Request: httpRequest}
	any := make(Anything)
	request.ReadEntity(&any)
	number, ok := any["Value"].(json.Number)
	if !ok {
		t.Fatal("read failed")
	}
	vint, err := number.Int64()
	if err != nil {
		t.Fatal("convert failed")
	}
	if vint != 4899710515899924123 {
		t.Fatal("read failed")
	}
	vfloat, err := number.Float64()
	if err != nil {
		t.Fatal("convert failed")
	}
	// match the default behaviour
	vstring := strconv.FormatFloat(vfloat, 'e', 15, 64)
	if vstring != "4.899710515899924e+18" {
		t.Fatal("convert float64 failed")
	}
}

func TestBodyParameter(t *testing.T) {
	bodyReader := strings.NewReader(`value1=42&value2=43`)
	httpRequest, _ := http.NewRequest("POST", "/test?value1=44", bodyReader) // POST and PUT body parameters take precedence over URL query string
	httpRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	request := NewRequest(httpRequest)
	v1, err := request.BodyParameter("value1")
	if err != nil {
		t.Error(err)
	}
	v2, err := request.BodyParameter("value2")
	if err != nil {
		t.Error(err)
	}
	if v1 != "42" || v2 != "43" {
		t.Fatal("read failed")
	}
}

func TestReadEntityUnkown(t *testing.T) {
	bodyReader := strings.NewReader("?")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/rubbish")
	request := NewRequest(httpRequest)
	sam := new(Sample)
	err := request.ReadEntity(sam)
	if err == nil {
		t.Fatal("read should be in error")
	}
}

func TestSetAttribute(t *testing.T) {
	bodyReader := strings.NewReader("?")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	request := NewRequest(httpRequest)
	request.SetAttribute("go", "there")
	there := request.Attribute("go")
	if there != "there" {
		t.Fatalf("missing request attribute:%v", there)
	}
}
<commit_msg>- test for get expected value if we have specify the field type correctly<commit_after>package restful

import (
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"testing"
)

func TestQueryParameter(t *testing.T) {
	hreq := http.Request{Method: "GET"}
	hreq.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
	rreq := Request{Request: &hreq}
	if rreq.QueryParameter("q") != "foo" {
		t.Errorf("q!=foo %#v", rreq)
	}
}

type Anything map[string]interface{}

type Number struct {
	ValueFloat float64
	ValueInt   int64
}

type Sample struct {
	Value string
}

func TestReadEntityXml(t *testing.T) {
	SetCacheReadEntity(true)
	bodyReader := strings.NewReader("<Sample><Value>42</Value></Sample>")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/xml")
	request := &Request{Request: httpRequest}
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
	if request.bodyContent == nil {
		t.Fatal("no expected cached bytes found")
	}
}

func TestReadEntityXmlNonCached(t *testing.T) {
	SetCacheReadEntity(false)
	bodyReader := strings.NewReader("<Sample><Value>42</Value></Sample>")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/xml")
	request := &Request{Request: httpRequest}
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
	if request.bodyContent != nil {
		t.Fatal("unexpected cached bytes found")
	}
}

func TestReadEntityJson(t *testing.T) {
	bodyReader := strings.NewReader(`{"Value" : "42"}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json")
	request := &Request{Request: httpRequest}
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
}

func TestReadEntityJsonCharset(t *testing.T) {
	bodyReader := strings.NewReader(`{"Value" : "42"}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json; charset=UTF-8")
	request := NewRequest(httpRequest)
	sam := new(Sample)
	request.ReadEntity(sam)
	if sam.Value != "42" {
		t.Fatal("read failed")
	}
}

func TestReadEntityJsonNumber(t *testing.T) {
	bodyReader := strings.NewReader(`{"Value" : 4899710515899924123}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json")
	request := &Request{Request: httpRequest}
	any := make(Anything)
	request.ReadEntity(&any)
	number, ok := any["Value"].(json.Number)
	if !ok {
		t.Fatal("read failed")
	}
	vint, err := number.Int64()
	if err != nil {
		t.Fatal("convert failed")
	}
	if vint != 4899710515899924123 {
		t.Fatal("read failed")
	}
	vfloat, err := number.Float64()
	if err != nil {
		t.Fatal("convert failed")
	}
	// match the default behaviour
	vstring := strconv.FormatFloat(vfloat, 'e', 15, 64)
	if vstring != "4.899710515899924e+18" {
		t.Fatal("convert float64 failed")
	}
}

func TestReadEntityJsonLong(t *testing.T) {
	bodyReader := strings.NewReader(`{"ValueFloat" : 4899710515899924123, "ValueInt": 4899710515899924123}`)
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/json")
	request := &Request{Request: httpRequest}
	number := new(Number)
	request.ReadEntity(&number)
	if number.ValueInt != 4899710515899924123 {
		t.Fatal("read failed")
	}
	// match the default behaviour
	vstring := strconv.FormatFloat(number.ValueFloat, 'e', 15, 64)
	if vstring != "4.899710515899924e+18" {
		t.Fatal("convert float64 failed")
	}
}

func TestBodyParameter(t *testing.T) {
	bodyReader := strings.NewReader(`value1=42&value2=43`)
	httpRequest, _ := http.NewRequest("POST", "/test?value1=44", bodyReader) // POST and PUT body parameters take precedence over URL query string
	httpRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	request := NewRequest(httpRequest)
	v1, err := request.BodyParameter("value1")
	if err != nil {
		t.Error(err)
	}
	v2, err := request.BodyParameter("value2")
	if err != nil {
		t.Error(err)
	}
	if v1 != "42" || v2 != "43" {
		t.Fatal("read failed")
	}
}

func TestReadEntityUnkown(t *testing.T) {
	bodyReader := strings.NewReader("?")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	httpRequest.Header.Set("Content-Type", "application/rubbish")
	request := NewRequest(httpRequest)
	sam := new(Sample)
	err := request.ReadEntity(sam)
	if err == nil {
		t.Fatal("read should be in error")
	}
}

func TestSetAttribute(t *testing.T) {
	bodyReader := strings.NewReader("?")
	httpRequest, _ := http.NewRequest("GET", "/test", bodyReader)
	request := NewRequest(httpRequest)
	request.SetAttribute("go", "there")
	there := request.Attribute("go")
	if there != "there" {
		t.Fatalf("missing request attribute:%v", there)
	}
}
<|endoftext|>


<commit_before>package muniverse

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"github.com/unixpickle/essentials"
	"github.com/unixpickle/muniverse/chrome"
)

const (
	portRange        = "9000-9999"
	defaultContainer = "unixpickle/muniverse:0.1.2"
)

const refreshTimeout = time.Minute

// SpecForName finds the first entry in EnvSpecs with the
// given name.
// If no entry is found, nil is returned.
func SpecForName(name string) *EnvSpec {
	for _, s := range EnvSpecs {
		if s.Name == name {
			return s
		}
	}
	return nil
}

// An Env controls a running environment.
type Env struct {
	spec     EnvSpec
	gameHost string

	containerID string
	devConn     *chrome.Conn
	lastScore   float64

	// Used to garbage collect the container if we
	// exit ungracefully.
	killSocket net.Conn
}

// NewEnv creates a new environment inside the default
// Docker container.
// This may take a few minutes to run the first time,
// since it has to download a large container.
func NewEnv(spec *EnvSpec) (*Env, error) {
	return NewEnvContainer(defaultContainer, spec)
}

// NewEnvContainer creates a new environment inside a
// Docker container of the given name.
func NewEnvContainer(container string, spec *EnvSpec) (env *Env, err error) {
	defer essentials.AddCtxTo("create environment", &err)

	id, err := dockerRun(container, spec)
	if err != nil {
		return
	}

	ports, err := dockerBoundPorts(id)
	if err != nil {
		return
	}

	killSock, err := net.Dial("tcp", "localhost:"+ports["1337/tcp"])
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			killSock.Close()
		}
	}()

	conn, err := connectDevTools("localhost:" + ports["9222/tcp"])
	if err != nil {
		return
	}

	return &Env{
		spec:        *spec,
		gameHost:    "localhost",
		containerID: id,
		devConn:     conn,
		killSocket:  killSock,
	}, nil
}

// NewEnvChrome connects to an existing Chrome DevTools
// server and runs an environment in there.
//
// The gameHost argument specifies where to load games.
// For example, gameHost might be "localhost:8080" if the
// game "Foobar" should be loaded from
// "http://localhost/Foobar".
//
// The Chrome instance must have at least one page open,
// since an open page is selected and used to run the
// environment.
func NewEnvChrome(host, gameHost string, spec *EnvSpec) (env *Env, err error) {
	defer essentials.AddCtxTo("create environment", &err)

	conn, err := connectDevTools(host)
	if err != nil {
		return
	}

	return &Env{
		spec:     *spec,
		gameHost: gameHost,
		devConn:  conn,
	}, nil
}

// Spec returns a copy of the specification used to create
// this environment.
func (e *Env) Spec() *EnvSpec {
	res := e.spec
	return &res
}

// Reset resets the environment and returns the first
// observation.
//
// This should be called before the first step.
// It should also be called every time an episode finishes
// before steps are taken for the next episode.
func (e *Env) Reset() (obs Obs, err error) {
	defer essentials.AddCtxTo("reset environment", &err)

	err = e.devConn.NavigateSync(e.envURL(), time.After(refreshTimeout))
	if err != nil {
		return
	}

	err = e.dealWithLoadError()
	if err != nil {
		return
	}

	err = e.devConn.EvalPromise("window.muniverse.init();", nil)
	if err != nil {
		return
	}
	err = e.devConn.EvalPromise("window.muniverse.score();", &e.lastScore)
	if err != nil {
		return
	}

	return e.captureObservation()
}

// Step takes a step in the environment.
// In particular, it sends the given events and advances
// the game by the given number of milliseconds.
// After this is complete, it captures an observation.
//
// If done is true, then the game has ended and no more
// steps should be taken before Reset is called.
// For convenience, the observation will be set even if
// the game has completed.
//
// The only supported event type is *chrome.MouseEvent.
func (e *Env) Step(millis int, events ...interface{}) (obs Obs, reward float64,
	done bool, err error) {
	defer essentials.AddCtxTo("step environment", &err)

	for _, event := range events {
		switch event := event.(type) {
		case *chrome.MouseEvent:
			err = e.devConn.DispatchMouseEvent(event)
			if err != nil {
				return
			}
		default:
			err = fmt.Errorf("unsupported event type: %T", event)
			return
		}
	}

	timeStr := strconv.Itoa(millis)
	err = e.devConn.EvalPromise("window.muniverse.step("+timeStr+");", &done)
	if err != nil {
		return
	}

	lastScore := e.lastScore
	err = e.devConn.EvalPromise("window.muniverse.score();", &e.lastScore)
	if err != nil {
		return
	}
	reward = e.lastScore - lastScore

	obs, err = e.captureObservation()
	return
}

// Close cleans up the resources associated with the
// environment.
// You should only call Close() once you are done using
// the environment.
func (e *Env) Close() (err error) {
	defer essentials.AddCtxTo("close environment", &err)

	errs := []error{
		e.devConn.Close(),
	}
	if e.containerID != "" {
		errs = append(errs, exec.Command("docker", "kill", e.containerID).Run())
	}

	if e.killSocket != nil {
		// TODO: look into if this can ever produce an error,
		// since the container might already have closed the
		// socket by now.
		//
		// We don't close this *before* stopping the container
		// since `docker kill` might fail if the container
		// already died and was cleaned up.
		e.killSocket.Close()
	}

	// Any calls after Close() should trigger simple errors.
	e.devConn = nil
	e.killSocket = nil

	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}

func (e *Env) envURL() string {
	return "http://" + e.gameHost + "/" + e.spec.Name
}

func (e *Env) captureObservation() (obs Obs, err error) {
	pngData, err := e.devConn.ScreenshotPNG()
	if err != nil {
		return
	}
	return pngObs(pngData), nil
}

func (e *Env) dealWithLoadError() error {
	// Sometimes, on macOS, loading the page in Chrome
	// initially gives a net::ERR_NETWORK_CHANGED error.
	// After a refresh, the error is usually fixed.
	//
	// We can check for this error semi-reliably by seeing
	// if the muniverse JS module has been loaded.

	var typeStr string
	err := e.devConn.EvalPromise("Promise.resolve(typeof muniverse);", &typeStr)
	if err != nil {
		return err
	}
	if typeStr == "undefined" {
		time.Sleep(time.Second * 5)
		return e.devConn.NavigateSync(e.envURL(), time.After(refreshTimeout))
	}
	return nil
}

func dockerRun(container string, spec *EnvSpec) (id string, err error) {
	args := []string{
		"run",
		"-p",
		portRange + ":9222",
		"-p",
		portRange + ":1337",
		"-d",   // Run in detached mode.
		"--rm", // Automatically delete the container.
		"-i",   // Give netcat a stdin to read from.
		container,
		fmt.Sprintf("--window-size=%d,%d", spec.Width, spec.Height),
	}

	output, err := exec.Command("docker", args...).Output()
	if err != nil {
		return "", essentials.AddCtx("docker run",
			fmt.Errorf("%s (make sure docker is up-to-date)", err))
	}

	return strings.TrimSpace(string(output)), nil
}

func dockerBoundPorts(containerID string) (mapping map[string]string, err error) {
	defer essentials.AddCtxTo("docker inspect", &err)
	rawJSON, err := exec.Command("docker", "inspect", containerID).Output()
	if err != nil {
		return nil, err
	}
	var info []struct {
		NetworkSettings struct {
			Ports map[string][]struct {
				HostPort string
			}
		}
	}
	if err := json.Unmarshal(rawJSON, &info); err != nil {
		return nil, err
	}
	if len(info) != 1 {
		return nil, errors.New("unexpected number of results")
	}
	rawMapping := info[0].NetworkSettings.Ports
	mapping = map[string]string{}
	for containerPort, hostPorts := range rawMapping {
		if len(hostPorts) != 1 {
			return nil, errors.New("unexpected number of host ports")
		}
		mapping[containerPort] = hostPorts[0].HostPort
	}
	return
}

func connectDevTools(host string) (conn *chrome.Conn, err error) {
	var endpoints []*chrome.Endpoint
	for i := 0; i < 5; i++ {
		endpoints, err = chrome.Endpoints(host)
		if err == nil {
			break
		}
		// Give Chrome a moment to start up if needed.
		time.Sleep(time.Second)
	}
	if err != nil {
		return
	}

	for _, ep := range endpoints {
		if ep.Type == "page" {
			return chrome.NewConn(ep.WebSocketURL)
		}
	}

	return nil, errors.New("no Chrome page endpoint")
}
<commit_msg>allow for "blind steps"<commit_after>package muniverse

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"github.com/unixpickle/essentials"
	"github.com/unixpickle/muniverse/chrome"
)

const (
	portRange        = "9000-9999"
	defaultContainer = "unixpickle/muniverse:0.1.2"
)

const refreshTimeout = time.Minute

// SpecForName finds the first entry in EnvSpecs with the
// given name.
// If no entry is found, nil is returned.
func SpecForName(name string) *EnvSpec {
	for _, s := range EnvSpecs {
		if s.Name == name {
			return s
		}
	}
	return nil
}

// An Env controls a running environment.
type Env struct {
	spec     EnvSpec
	gameHost string

	containerID string
	devConn     *chrome.Conn
	lastScore   float64

	// Used to garbage collect the container if we
	// exit ungracefully.
	killSocket net.Conn
}

// NewEnv creates a new environment inside the default
// Docker container.
// This may take a few minutes to run the first time,
// since it has to download a large container.
func NewEnv(spec *EnvSpec) (*Env, error) {
	return NewEnvContainer(defaultContainer, spec)
}

// NewEnvContainer creates a new environment inside a
// Docker container of the given name.
func NewEnvContainer(container string, spec *EnvSpec) (env *Env, err error) {
	defer essentials.AddCtxTo("create environment", &err)

	id, err := dockerRun(container, spec)
	if err != nil {
		return
	}

	ports, err := dockerBoundPorts(id)
	if err != nil {
		return
	}

	killSock, err := net.Dial("tcp", "localhost:"+ports["1337/tcp"])
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			killSock.Close()
		}
	}()

	conn, err := connectDevTools("localhost:" + ports["9222/tcp"])
	if err != nil {
		return
	}

	return &Env{
		spec:        *spec,
		gameHost:    "localhost",
		containerID: id,
		devConn:     conn,
		killSocket:  killSock,
	}, nil
}

// NewEnvChrome connects to an existing Chrome DevTools
// server and runs an environment in there.
//
// The gameHost argument specifies where to load games.
// For example, gameHost might be "localhost:8080" if the
// game "Foobar" should be loaded from
// "http://localhost/Foobar".
//
// The Chrome instance must have at least one page open,
// since an open page is selected and used to run the
// environment.
func NewEnvChrome(host, gameHost string, spec *EnvSpec) (env *Env, err error) {
	defer essentials.AddCtxTo("create environment", &err)

	conn, err := connectDevTools(host)
	if err != nil {
		return
	}

	return &Env{
		spec:     *spec,
		gameHost: gameHost,
		devConn:  conn,
	}, nil
}

// Spec returns a copy of the specification used to create
// this environment.
func (e *Env) Spec() *EnvSpec {
	res := e.spec
	return &res
}

// Reset resets the environment to a starting state.
//
// This should be called before the first step.
// It should also be called every time an episode finishes
// before steps are taken for the next episode.
func (e *Env) Reset() (err error) {
	defer essentials.AddCtxTo("reset environment", &err)

	err = e.devConn.NavigateSync(e.envURL(), time.After(refreshTimeout))
	if err != nil {
		return
	}

	err = e.dealWithLoadError()
	if err != nil {
		return
	}

	err = e.devConn.EvalPromise("window.muniverse.init();", nil)
	if err != nil {
		return
	}
	err = e.devConn.EvalPromise("window.muniverse.score();", &e.lastScore)

	return
}

// Step takes a step in the environment.
// In particular, it sends the given events and advances
// the game by the given number of milliseconds.
//
// If done is true, then the episode has ended and no more
// steps should be taken before Reset is called.
// However, observations may be made even after the
// episode has ended.
//
// The only supported event type is *chrome.MouseEvent.
func (e *Env) Step(millis int, events ...interface{}) (reward float64,
	done bool, err error) {
	defer essentials.AddCtxTo("step environment", &err)

	for _, event := range events {
		switch event := event.(type) {
		case *chrome.MouseEvent:
			err = e.devConn.DispatchMouseEvent(event)
			if err != nil {
				return
			}
		default:
			err = fmt.Errorf("unsupported event type: %T", event)
			return
		}
	}

	timeStr := strconv.Itoa(millis)
	err = e.devConn.EvalPromise("window.muniverse.step("+timeStr+");", &done)
	if err != nil {
		return
	}

	lastScore := e.lastScore
	err = e.devConn.EvalPromise("window.muniverse.score();", &e.lastScore)
	if err != nil {
		return
	}
	reward = e.lastScore - lastScore

	return
}

// Observe produces an observation for the current state.
func (e *Env) Observe() (obs Obs, err error) {
	pngData, err := e.devConn.ScreenshotPNG()
	if err != nil {
		return
	}
	return pngObs(pngData), nil
}

// Close cleans up the resources associated with the
// environment.
// You should only call Close() once you are done using
// the environment.
func (e *Env) Close() (err error) {
	defer essentials.AddCtxTo("close environment", &err)

	errs := []error{
		e.devConn.Close(),
	}
	if e.containerID != "" {
		errs = append(errs, exec.Command("docker", "kill", e.containerID).Run())
	}

	if e.killSocket != nil {
		// TODO: look into if this can ever produce an error,
		// since the container might already have closed the
		// socket by now.
		//
		// We don't close this *before* stopping the container
		// since `docker kill` might fail if the container
		// already died and was cleaned up.
		e.killSocket.Close()
	}

	// Any calls after Close() should trigger simple errors.
	e.devConn = nil
	e.killSocket = nil

	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}

func (e *Env) envURL() string {
	return "http://" + e.gameHost + "/" + e.spec.Name
}

func (e *Env) dealWithLoadError() error {
	// Sometimes, on macOS, loading the page in Chrome
	// initially gives a net::ERR_NETWORK_CHANGED error.
	// After a refresh, the error is usually fixed.
	//
	// We can check for this error semi-reliably by seeing
	// if the muniverse JS module has been loaded.

	var typeStr string
	err := e.devConn.EvalPromise("Promise.resolve(typeof muniverse);", &typeStr)
	if err != nil {
		return err
	}
	if typeStr == "undefined" {
		time.Sleep(time.Second * 5)
		return e.devConn.NavigateSync(e.envURL(), time.After(refreshTimeout))
	}
	return nil
}

func dockerRun(container string, spec *EnvSpec) (id string, err error) {
	args := []string{
		"run",
		"-p",
		portRange + ":9222",
		"-p",
		portRange + ":1337",
		"-d",   // Run in detached mode.
		"--rm", // Automatically delete the container.
		"-i",   // Give netcat a stdin to read from.
		container,
		fmt.Sprintf("--window-size=%d,%d", spec.Width, spec.Height),
	}

	output, err := exec.Command("docker", args...).Output()
	if err != nil {
		return "", essentials.AddCtx("docker run",
			fmt.Errorf("%s (make sure docker is up-to-date)", err))
	}

	return strings.TrimSpace(string(output)), nil
}

func dockerBoundPorts(containerID string) (mapping map[string]string, err error) {
	defer essentials.AddCtxTo("docker inspect", &err)
	rawJSON, err := exec.Command("docker", "inspect", containerID).Output()
	if err != nil {
		return nil, err
	}
	var info []struct {
		NetworkSettings struct {
			Ports map[string][]struct {
				HostPort string
			}
		}
	}
	if err := json.Unmarshal(rawJSON, &info); err != nil {
		return nil, err
	}
	if len(info) != 1 {
		return nil, errors.New("unexpected number of results")
	}
	rawMapping := info[0].NetworkSettings.Ports
	mapping = map[string]string{}
	for containerPort, hostPorts := range rawMapping {
		if len(hostPorts) != 1 {
			return nil, errors.New("unexpected number of host ports")
		}
		mapping[containerPort] = hostPorts[0].HostPort
	}
	return
}

func connectDevTools(host string) (conn *chrome.Conn, err error) {
	var endpoints []*chrome.Endpoint
	for i := 0; i < 5; i++ {
		endpoints, err = chrome.Endpoints(host)
		if err == nil {
			break
		}
		// Give Chrome a moment to start up if needed.
		time.Sleep(time.Second)
	}
	if err != nil {
		return
	}

	for _, ep := range endpoints {
		if ep.Type == "page" {
			return chrome.NewConn(ep.WebSocketURL)
		}
	}

	return nil, errors.New("no Chrome page endpoint")
}
<|endoftext|>


<commit_before>package yiigo

import (
	"errors"
	"path/filepath"
	"sync"

	toml "github.com/pelletier/go-toml"
)

type env struct {
	tree  *toml.Tree
	mutex sync.RWMutex
}

// Env enviroment
var Env *env

// ErrNil returned when config not found.
var ErrNil = errors.New("config not found")

// loadEnv load env file
func loadEnv(path string) {
	abs, _ := filepath.Abs(path)
	tomlTree, err := toml.LoadFile(abs)

	if err != nil {
		panic(err)
	}

	Env = &env{tree: tomlTree}
}

// String return string
func (e *env) String(key string, defVal ...string) string {
	val := ""

	if len(defVal) > 0 {
		val = defVal[0]
	}

	conf := e.Get(key)

	if conf == nil {
		return val
	}

	if v, ok := conf.(string); ok {
		val = v
	}

	return val
}

// Int return int
func (e *env) Int(key string, defVal ...int) int {
	val := 0

	if len(defVal) > 0 {
		val = defVal[0]
	}

	conf := e.Get(key)

	if conf == nil {
		return val
	}

	if v, ok := conf.(int); ok {
		val = v
	}

	return val
}

// Int64 return int64
func (e *env) Int64(key string, defVal ...int64) int64 {
	var val int64

	if len(defVal) > 0 {
		val = defVal[0]
	}

	conf := e.Get(key)

	if conf == nil {
		return val
	}

	if v, ok := conf.(int64); ok {
		val = v
	}

	return val
}

// Float64 return float64
func (e *env) Float64(key string, defVal ...float64) float64 {
	var val float64

	if len(defVal) > 0 {
		val = defVal[0]
	}

	conf := e.Get(key)

	if conf == nil {
		return val
	}

	if v, ok := conf.(float64); ok {
		val = v
	}

	return val
}

// Bool return bool
func (e *env) Bool(key string, defVal ...bool) bool {
	var val bool

	if len(defVal) > 0 {
		val = defVal[0]
	}

	conf := e.Get(key)

	if conf == nil {
		return val
	}

	if v, ok := conf.(bool); ok {
		val = v
	}

	return val
}

// ToMap return map[string]interface{}
func (e *env) ToMap(key string) map[string]interface{} {
	v := e.Get(key)

	if v == nil {
		return nil
	}

	if node, ok := v.(*toml.Tree); ok {
		return node.ToMap()
	}

	return nil
}

// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by dest
func (e *env) Unmarshal(key string, dest interface{}) error {
	conf := e.Get(key)

	if conf == nil {
		return ErrNil
	}

	if node, ok := conf.(*toml.Tree); ok {
		err := node.Unmarshal(dest)

		return err
	}

	return errors.New("value is not a tree of toml")
}

// Get return interface{}
func (e *env) Get(key string) interface{} {
	e.mutex.RLock()
	defer e.mutex.RUnlock()

	v := e.tree.Get(key)

	return v
}
<commit_msg>fix some deficiencies<commit_after>package yiigo

import (
	"errors"
	"path/filepath"
	"sync"

	toml "github.com/pelletier/go-toml"
)

type env struct {
	tree  *toml.Tree
	mutex sync.RWMutex
}

// Env enviroment
var Env *env

// ErrNil returned when config not found.
var ErrNil = errors.New("config not found")

// loadEnv load env file
func loadEnv(path string) {
	abs, _ := filepath.Abs(path)
	tomlTree, err := toml.LoadFile(abs)

	if err != nil {
		panic(err)
	}

	Env = &env{tree: tomlTree}
}

// String return string
func (e *env) String(key string, defaultValue ...string) string {
	dv := ""

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	if v, ok := i.(string); ok {
		return v
	}

	return dv
}

// Int return int
func (e *env) Int(key string, defaultValue ...int) int {
	dv := 0

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	if v, ok := i.(int64); ok {
		return int(v)
	}

	return dv
}

// Int64 return int64
func (e *env) Int64(key string, defaultValue ...int64) int64 {
	var dv int64

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	if v, ok := i.(int64); ok {
		return v
	}

	return dv
}

// Float64 return float64
func (e *env) Float64(key string, defaultValue ...float64) float64 {
	var dv float64

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	if v, ok := i.(float64); ok {
		return v
	}

	return dv
}

// Bool return bool
func (e *env) Bool(key string, defaultValue ...bool) bool {
	var dv bool

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	if v, ok := i.(bool); ok {
		return v
	}

	return dv
}

// ToMap return map[string]interface{}
func (e *env) ToMap(key string) map[string]interface{} {
	i := e.Get(key)

	if v, ok := i.(*toml.Tree); ok {
		return v.ToMap()
	}

	return nil
}

// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by dest
func (e *env) Unmarshal(key string, dest interface{}) error {
	i := e.Get(key)

	if i == nil {
		return ErrNil
	}

	if v, ok := i.(*toml.Tree); ok {
		err := v.Unmarshal(dest)

		return err
	}

	return errors.New("value is not a tree of toml")
}

// Get return interface{}
func (e *env) Get(key string) interface{} {
	e.mutex.RLock()
	defer e.mutex.RUnlock()

	i := e.tree.Get(key)

	return i
}
<|endoftext|>


<commit_before>// Copyright 2015 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 gcm provides send and receive GCM functionality.
package gcm

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/mattn/go-xmpp"
)

const (
	httpAddress = "https://android.googleapis.com/gcm/send"
	xmppHost    = "gcm.googleapis.com"
	xmppPort    = "5235"
	xmppAddress = xmppHost + ":" + xmppPort
)

var (
	// DebugMode determines whether to have verbose logging.
	DebugMode = true
)

func debug(m string, v interface{}) {
	if DebugMode {
		log.Printf(m+":%+v", v)
	}
}

// downstream is a downstream (server -> client) message.
type downstream struct {
	To   string  `json:"to,omitempty"`
	Data Message `json:"data,omitempty"`
}

// upstream is an upstream (client -> server) message.
type upstream struct {
	From string  `json:"from"`
	Data Message `json:"data,omitempty"`
}

// Message is the custom data passed with every GCM message.
type Message map[string]interface{}

// StopChannel is a channel type to stop the server.
type StopChannel chan bool

// MessageHandler is the type for a function that handles a GCM message.
type MessageHandler func(from string, m Message) error

// Send sends a downstream message to a given device.
func Send(apiKey, to string, m Message) error {
	bs, err := json.Marshal(&downstream{To: to, Data: m})
	if err != nil {
		return fmt.Errorf("error marshalling message>%v", err)
	}
	debug("sending", string(bs))
	req, err := http.NewRequest("POST", httpAddress, bytes.NewReader(bs))
	if err != nil {
		return fmt.Errorf("error creating request>%v", err)
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", authHeader(apiKey))
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error making request>%v", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error reading body>%v", err)
	}
	debug("response body", string(body))
	return nil
}

// Listen blocks and connects to GCM waiting for messages, calling the handler
// for every "normal" type message. An optional stop channel can be provided to
// stop listening.
func Listen(senderId, apiKey string, h MessageHandler, stop StopChannel) error {
	cl, err := xmpp.NewClient(xmppAddress, xmppUser(senderId), apiKey, DebugMode)
	if err != nil {
		return fmt.Errorf("error connecting client>%v", err)
	}
	if stop != nil {
		go func() {
			select {
			case <-stop:
				cl.Close()
			}
		}()
	}
	for {
		stanza, err := cl.Recv()
		if err != nil {
			// This is likely fatal, so return.
			return fmt.Errorf("error on Recv>%v", err)
		}
		v, ok := stanza.(xmpp.Chat)
		if !ok {
			continue
		}
		switch v.Type {
		case "normal":
			up := &upstream{}
			json.Unmarshal([]byte(v.Other[0]), up)
			go h(up.From, up.Data)
		case "error":
			debug("error response", v)
		}
	}
	return nil
}

// authHeader generates an authorization header value for an api key.
func authHeader(apiKey string) string {
	return fmt.Sprintf("key=%v", apiKey)
}

// xmppUser generates an xmpp username from a sender ID.
func xmppUser(senderId string) string {
	return senderId + "@" + xmppHost
}
<commit_msg>(breaking change) refactor Send to add all available options<commit_after>// Copyright 2015 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 gcm provides send and receive GCM functionality.
package gcm

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/mattn/go-xmpp"
)

const (
	httpAddress = "https://android.googleapis.com/gcm/send"
	xmppHost    = "gcm.googleapis.com"
	xmppPort    = "5235"
	xmppAddress = xmppHost + ":" + xmppPort
)

var (
	// DebugMode determines whether to have verbose logging.
	DebugMode = true
)

func debug(m string, v interface{}) {
	if DebugMode {
		log.Printf(m+":%+v", v)
	}
}

// Message is a downstream (server -> client) message.
type Message struct {
	To                    string       `json:"to,omitempty"`
	RegistrationIds       []string     `json:"registration_ids,omitempty"`
	NotificationKey       string       `json:"notification_key,omitempty"`
	CollapseKey           string       `json:"collapse_key,omitempty"`
	DelayWhileIdle        bool         `json:"delay_while_idle,omitempty"`
	TimeToLive            uint         `json:"time_to_live,omitempty"`
	RestrictedPackageName string       `json:"restricted_package_name,omitempty"`
	DryRun                bool         `json:"dry_run,omitempty"`
	Data                  Data         `json:"data,omitempty"`
	Notification          Notification `json:"notification,omitempty"`
}

// upstream is an upstream (client -> server) message.
type upstream struct {
	From      string `json:"from"`
	Category  string `json:"category"`
	MessageId string `json:"message_id"`
	Data      Data   `json:"data,omitempty"`
}

// Data is the custom data passed with every GCM message.
type Data map[string]interface{}

// A GCM notification
type Notification struct {
	Text        string `json:"text,omitempty"`
	Title       string `json:"title,omitempty"`
	Badge       string `json:"badge,omitempty"`
	ClickAction string `json:"click-action,omitempty"`
}

// StopChannel is a channel type to stop the server.
type StopChannel chan bool

// MessageHandler is the type for a function that handles a GCM message.
type MessageHandler func(from string, d Data) error

// Send sends a downstream message to a given device.
func Send(apiKey string, m Message) error {
	if m.To == "" && m.NotificationKey == "" && len(m.RegistrationIds) == 0 {
		return errors.New("One of To, RegistrationIds or NotificationKey must be defined for the message.")
	}
	bs, err := json.Marshal(m)
	if err != nil {
		return fmt.Errorf("error marshalling message>%v", err)
	}
	debug("sending", string(bs))
	req, err := http.NewRequest("POST", httpAddress, bytes.NewReader(bs))
	if err != nil {
		return fmt.Errorf("error creating request>%v", err)
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", authHeader(apiKey))
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error making request>%v", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error reading body>%v", err)
	}
	debug("response body", string(body))
	return nil
}

// Listen blocks and connects to GCM waiting for messages, calling the handler
// for every "normal" type message. An optional stop channel can be provided to
// stop listening.
func Listen(senderId, apiKey string, h MessageHandler, stop StopChannel) error {
	cl, err := xmpp.NewClient(xmppAddress, xmppUser(senderId), apiKey, DebugMode)
	if err != nil {
		return fmt.Errorf("error connecting client>%v", err)
	}
	if stop != nil {
		go func() {
			select {
			case <-stop:
				cl.Close()
			}
		}()
	}
	for {
		stanza, err := cl.Recv()
		if err != nil {
			// This is likely fatal, so return.
			return fmt.Errorf("error on Recv>%v", err)
		}
		v, ok := stanza.(xmpp.Chat)
		if !ok {
			continue
		}
		switch v.Type {
		case "normal":
			up := &upstream{}
			json.Unmarshal([]byte(v.Other[0]), up)
			go h(up.From, up.Data)
		case "error":
			debug("error response", v)
		}
	}
	return nil
}

// authHeader generates an authorization header value for an api key.
func authHeader(apiKey string) string {
	return fmt.Sprintf("key=%v", apiKey)
}

// xmppUser generates an xmpp username from a sender ID.
func xmppUser(senderId string) string {
	return senderId + "@" + xmppHost
}
<|endoftext|>


<commit_before>package captain // import "github.com/harbur/captain"

import (
	"regexp"
	"strings"
)

func getRevision() string {
	res, _ := oneliner("git", "rev-parse", "--short", "HEAD")
	return res
}

func getBranches() []string {
	branch, _ := oneliner("git", "symbolic-ref", "--short", "-q", "HEAD")
	tag, err := oneliner("git", "tag", "--points-at", "HEAD")
	if err == nil && tag != "" {
		branch = tag
	}

	// If branch string is empty return an empty list
	var branches =[]string{}

	if (branch != "") {
		// Git tag list is separated in multi-lines. Let's put it in an array
		branches = strings.Split(branch, "\n")
	}

	for key := range branches {
		// Remove start of "heads/origin" if exist
		r := regexp.MustCompile("^heads\\/origin\\/")
		branches[key] = r.ReplaceAllString(branches[key], "")

		// Remove start of "remotes/origin" if exist
		r = regexp.MustCompile("^remotes\\/origin\\/")
		branches[key] = r.ReplaceAllString(branches[key], "")

		// Replace all "/" with "."
		branches[key] = strings.Replace(branches[key], "/", ".", -1)

		// Replace all "~" with "."
		branches[key] = strings.Replace(branches[key], "~", ".", -1)
	}

	return branches
}

func isDirty() bool {
	res, _ := oneliner("git", "status", "--porcelain")
	return len(res) > 0
}

func isGit() bool {
	res := getRevision()
	return len(res) > 0
}
<commit_msg>Capture all branches, not only working branch<commit_after>package captain // import "github.com/harbur/captain"

import (
	"regexp"
	"strings"
)

func getRevision() string {
	res, _ := oneliner("git", "rev-parse", "--short", "HEAD")
	return res
}

func getBranches() []string {
	// Labels (branches + tags)
	var labels =[]string{}

	branches,_ := oneliner("git", "branch", "--no-column", "--contains", "HEAD")
	if (branches != "") {
		// Remove asterisk from branches list
		r := regexp.MustCompile("[\\* ] ")
		branches = r.ReplaceAllString(branches, "")
		// Branches list is separated by spaces. Let's put it in an array
		labels=append(labels,strings.Split(branches, "\n")...)
	}

	tags, _ := oneliner("git", "tag", "--points-at", "HEAD")

	if (tags != "") {
		// Git tag list is separated by multi-lines. Let's put it in an array
		labels=append(labels,strings.Split(tags, "\n")...)
	}

	for key := range labels {
		// Remove start of "heads/origin" if exist
		r := regexp.MustCompile("^heads\\/origin\\/")
		labels[key] = r.ReplaceAllString(labels[key], "")

		// Remove start of "remotes/origin" if exist
		r = regexp.MustCompile("^remotes\\/origin\\/")
		labels[key] = r.ReplaceAllString(labels[key], "")

		// Replace all "/" with "."
		labels[key] = strings.Replace(labels[key], "/", ".", -1)

		// Replace all "~" with "."
		labels[key] = strings.Replace(labels[key], "~", ".", -1)
	}

	return labels
}

func isDirty() bool {
	res, _ := oneliner("git", "status", "--porcelain")
	return len(res) > 0
}

func isGit() bool {
	res := getRevision()
	return len(res) > 0
}
<|endoftext|>


<commit_before>// +build linux freebsd

package configs

type FreezerState string

const (
	Undefined FreezerState = ""
	Frozen    FreezerState = "FROZEN"
	Thawed    FreezerState = "THAWED"
)

type Cgroup struct {
	Name string `json:"name"`

	// name of parent cgroup or slice
	Parent string `json:"parent"`

	// ScopePrefix decribes prefix for the scope name
	ScopePrefix string `json:"scope_prefix"`

	// Paths represent the cgroups paths to join
	Paths map[string]string

	// Resources contains various cgroups settings to apply
	*Resources
}

type Resources struct {
	// If this is true allow access to any kind of device within the container.  If false, allow access only to devices explicitly listed in the allowed_devices list.
	AllowAllDevices bool `json:"allow_all_devices"`

	AllowedDevices []*Device `json:"allowed_devices"`

	DeniedDevices []*Device `json:"denied_devices"`

	// Memory limit (in bytes)
	Memory int64 `json:"memory"`

	// Memory reservation or soft_limit (in bytes)
	MemoryReservation int64 `json:"memory_reservation"`

	// Total memory usage (memory + swap); set `-1' to disable swap
	MemorySwap int64 `json:"memory_swap"`

	// Kernel memory limit (in bytes)
	KernelMemory int64 `json:"kernel_memory"`

	// CPU shares (relative weight vs. other containers)
	CpuShares int64 `json:"cpu_shares"`

	// CPU hardcap limit (in usecs). Allowed cpu time in a given period.
	CpuQuota int64 `json:"cpu_quota"`

	// CPU period to be used for hardcapping (in usecs). 0 to use system default.
	CpuPeriod int64 `json:"cpu_period"`

	// How many time CPU will use in realtime scheduling (in usecs).
	CpuRtRuntime int64 `json:"cpu_quota"`

	// CPU period to be used for realtime scheduling (in usecs).
	CpuRtPeriod int64 `json:"cpu_period"`

	// CPU to use
	CpusetCpus string `json:"cpuset_cpus"`

	// MEM to use
	CpusetMems string `json:"cpuset_mems"`

	// Process limit; set <= `0' to disable limit.
	PidsLimit int64 `json:"pids_limit"`

	// Specifies per cgroup weight, range is from 10 to 1000.
	BlkioWeight uint16 `json:"blkio_weight"`

	// Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, cfq scheduler only
	BlkioLeafWeight uint16 `json:"blkio_leaf_weight"`

	// Weight per cgroup per device, can override BlkioWeight.
	BlkioWeightDevice []*WeightDevice `json:"blkio_weight_device"`

	// IO read rate limit per cgroup per device, bytes per second.
	BlkioThrottleReadBpsDevice []*ThrottleDevice `json:"blkio_throttle_read_bps_device"`

	// IO write rate limit per cgroup per divice, bytes per second.
	BlkioThrottleWriteBpsDevice []*ThrottleDevice `json:"blkio_throttle_write_bps_device"`

	// IO read rate limit per cgroup per device, IO per second.
	BlkioThrottleReadIOPSDevice []*ThrottleDevice `json:"blkio_throttle_read_iops_device"`

	// IO write rate limit per cgroup per device, IO per second.
	BlkioThrottleWriteIOPSDevice []*ThrottleDevice `json:"blkio_throttle_write_iops_device"`

	// set the freeze value for the process
	Freezer FreezerState `json:"freezer"`

	// Hugetlb limit (in bytes)
	HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"`

	// Whether to disable OOM Killer
	OomKillDisable bool `json:"oom_kill_disable"`

	// Tuning swappiness behaviour per cgroup
	MemorySwappiness int64 `json:"memory_swappiness"`

	// Set priority of network traffic for container
	NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap"`

	// Set class identifier for container's network packets
	NetClsClassid string `json:"net_cls_classid"`
}
<commit_msg>Fix comment of swap limit<commit_after>// +build linux freebsd

package configs

type FreezerState string

const (
	Undefined FreezerState = ""
	Frozen    FreezerState = "FROZEN"
	Thawed    FreezerState = "THAWED"
)

type Cgroup struct {
	Name string `json:"name"`

	// name of parent cgroup or slice
	Parent string `json:"parent"`

	// ScopePrefix decribes prefix for the scope name
	ScopePrefix string `json:"scope_prefix"`

	// Paths represent the cgroups paths to join
	Paths map[string]string

	// Resources contains various cgroups settings to apply
	*Resources
}

type Resources struct {
	// If this is true allow access to any kind of device within the container.  If false, allow access only to devices explicitly listed in the allowed_devices list.
	AllowAllDevices bool `json:"allow_all_devices"`

	AllowedDevices []*Device `json:"allowed_devices"`

	DeniedDevices []*Device `json:"denied_devices"`

	// Memory limit (in bytes)
	Memory int64 `json:"memory"`

	// Memory reservation or soft_limit (in bytes)
	MemoryReservation int64 `json:"memory_reservation"`

	// Total memory usage (memory + swap); set `-1` to enable unlimited swap
	MemorySwap int64 `json:"memory_swap"`

	// Kernel memory limit (in bytes)
	KernelMemory int64 `json:"kernel_memory"`

	// CPU shares (relative weight vs. other containers)
	CpuShares int64 `json:"cpu_shares"`

	// CPU hardcap limit (in usecs). Allowed cpu time in a given period.
	CpuQuota int64 `json:"cpu_quota"`

	// CPU period to be used for hardcapping (in usecs). 0 to use system default.
	CpuPeriod int64 `json:"cpu_period"`

	// How many time CPU will use in realtime scheduling (in usecs).
	CpuRtRuntime int64 `json:"cpu_quota"`

	// CPU period to be used for realtime scheduling (in usecs).
	CpuRtPeriod int64 `json:"cpu_period"`

	// CPU to use
	CpusetCpus string `json:"cpuset_cpus"`

	// MEM to use
	CpusetMems string `json:"cpuset_mems"`

	// Process limit; set <= `0' to disable limit.
	PidsLimit int64 `json:"pids_limit"`

	// Specifies per cgroup weight, range is from 10 to 1000.
	BlkioWeight uint16 `json:"blkio_weight"`

	// Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, cfq scheduler only
	BlkioLeafWeight uint16 `json:"blkio_leaf_weight"`

	// Weight per cgroup per device, can override BlkioWeight.
	BlkioWeightDevice []*WeightDevice `json:"blkio_weight_device"`

	// IO read rate limit per cgroup per device, bytes per second.
	BlkioThrottleReadBpsDevice []*ThrottleDevice `json:"blkio_throttle_read_bps_device"`

	// IO write rate limit per cgroup per divice, bytes per second.
	BlkioThrottleWriteBpsDevice []*ThrottleDevice `json:"blkio_throttle_write_bps_device"`

	// IO read rate limit per cgroup per device, IO per second.
	BlkioThrottleReadIOPSDevice []*ThrottleDevice `json:"blkio_throttle_read_iops_device"`

	// IO write rate limit per cgroup per device, IO per second.
	BlkioThrottleWriteIOPSDevice []*ThrottleDevice `json:"blkio_throttle_write_iops_device"`

	// set the freeze value for the process
	Freezer FreezerState `json:"freezer"`

	// Hugetlb limit (in bytes)
	HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"`

	// Whether to disable OOM Killer
	OomKillDisable bool `json:"oom_kill_disable"`

	// Tuning swappiness behaviour per cgroup
	MemorySwappiness int64 `json:"memory_swappiness"`

	// Set priority of network traffic for container
	NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap"`

	// Set class identifier for container's network packets
	NetClsClassid string `json:"net_cls_classid"`
}
<|endoftext|>